Hướng dẫn tự học Design Pattern trong C#

    10

    Design Pattern hay Mẫu thiết kế là một chủ đề rất quan trọng đối với lập trình viên. Bạn rất khó phát triển sự nghiệp lập trình viên nếu không biết/không hiểu/không vận dụng được các mẫu thiết kế trong giải pháp của mình.

    Tập bài giảng này sẽ dành trọn vẹn để hướng dẫn bạn sử dụng các mẫu thiết kế phổ biến với cài đặt trên ngôn ngữ C#. Hi vọng nó sẽ giúp ích ít nhiều cho bạn trên con đường trở thành lập trình viên chuyên nghiệp.

    Vai trò của Design pattern

    Design Pattern là một dạng “bài toán mẫu” trong lập trình. Đó là những giải pháp cho những vấn đề thường gặp trong lập trình mà nhiều thế hệ lập trình viên đã đúc kết và chứng minh tính hiệu quả của nó.

    Nếu bạn từng nghe thấy những từ như Singleton, Decorator, Proxy, Bridge, Memento, Mediator v.v. trong những tài liệu về lập trình thì đó chính là tên của một số Design Pattern phổ biến.

    Việc sử dụng và kết hợp hợp lý các Design pattern giúp lập trình viên nhanh chóng đưa ra các giải pháp và thiết kế phù hợp. Nếu sử dụng tốt các mẫu thiết kế, bạn không cần tự mình “phát minh lại cái bánh xe”. Thay vào đó, bạn có thể áp dụng ngay các Design pattern phù hợp cho bài toán của mình.

    Design pattern có thể xem như một dạng ngôn ngữ cấp cao giúp lập trình viên mô tả giải pháp của mình cũng như thảo luận giải pháp cho những vấn đề phổ biến trong phát triển ứng dụng. Loại ngôn ngữ này bao gồm tên gọi của các giải pháp đã được ghi nhận cùng các thành phần của giải pháp đó.

    Cùng lấy một ví dụ. Giả sử bạn gặp phải yêu cầu như thế này trong thiết kế: làm sao để trong cả chương trình chỉ tạo ra một object duy nhất của class. Đừng nghĩ đây là một yêu cầu buồn cười. Nó rất phổ biến đấy ạ. Khi bạn xây dựng hệ thống log cho ứng dụng, hoặc khi bạn xử lý file cấu hình, bạn sẽ đụng chạm tới yêu cầu này.

    Khi này bạn không cần phải mất công suy nghĩ cách kết hợp các tính năng của ngôn ngữ nữa. Bạn có thể áp dụng ngay lập tức mẫu thiết kế Singleton. “Singleton” giúp mô tả rõ ràng giải pháp “tạo ra một object duy nhất của class” trong chương trình. Khi một lập trình viên khác nghe thấy “Singleton”, anh ta hiểu ngay bạn đang muốn xử lý vấn đề gì.

    Rất đáng tiếc rằng trong các chương trình đào tạo không dành đủ thời lượng cần thiết cho nội dung về Design pattern. Thậm chí rất nhiều “lập trình viên” tốt nghiệp đại học không hề biết gì về Design pattern.

    Trong tập bài giảng này Tự học ICT sẽ giúp các bạn nắm được và vận dụng các Design pattern phổ biến trong lập trình. Việc thực thi các Design pattern này được thể hiện bằng ngôn ngữ lập trình C#. Dĩ nhiên, khi nắm được cách thực thi trên một ngôn ngữ, bạn có thể dễ dàng chuyển đổi nó sang bất kỳ ngôn ngữ nào có tính năng tương tự như C++, Java hay Python.

    Các Design pattern cổ điển

    Design pattern được giới thiệu trong cuốn sách nổi tiếng “Design Patterns: Elements of Reusable Object-Oriented Software” của nhóm tác giả Erich Gamma, Richard Helm, Ralph Johnson, và John Vlissides.

    Cuốn sách này trình bày tổng cộng 23 Design pattern. Mỗi Design pattern có một tên gọi riêng và thường được mô tả bằng một sơ đồ UML. Hiện nay chúng được gọi là các mẫu thiết kế cổ điển.

    23 mẫu thiết kế cổ điển được chia là 3 nhóm: Creational, Structural, và Behavioral. Trong tập bài giảng này chúng ta sẽ lần lượt học tất cả các mẫu thuộc về 3 nhóm này.

    Theo thời gian, nhiều mẫu thiết kế mới xuất hiện. Có những mẫu thiết kế mới áp dụng cho những mảng chuyên biệt như kiến trúc phần mềm, giao diện người dùng, v.v.. Nó tạo ra sự phân mảng trong các mẫu thiết kế và cũng gây nhiều nhầm lẫn cho người mới bắt đầu. Do vậy các tài liệu về mẫu thiết kế thường chỉ tập trung vào 23 mẫu cổ điển đã được chấp nhận rộng rãi.

    Lưu ý rằng, có những mẫu thiết kế thông dụng hơn những mẫu khác. Có những mẫu được áp dụng trong những tình huống khá đặc thù mà bình thường bạn sẽ ít khi phải xử lý.

    Do vậy, bạn không nhất thiết phải nắm trọn vẹn tất cả 23 mẫu này. Hãy tập trung cho những mẫu thông dụng nhất mà công việc có thể gặp phải. Những mẫu ít thông dụng hơn bạn nên nắm ý tưởng của nó để khi cần thiết sẽ nghiên cứu sâu hơn. Mức độ phổ biến và những tình huống áp dụng sẽ được trình bày trong bài học tương ứng về mẫu thiết kế đó.

    Các Design pattern này đầu tiên được thực hiện trên C++ và Smalltalk. Sau đó xuất hiện những tài liệu thực hiện trên các ngôn ngữ lập trình khác như Java, Visual Basic, Python, JavaScript, C#, v.v..

    Tùy thuộc vào công cụ mà ngôn ngữ cung cấp, việc thực thi mẫu thiết kế có thể có đôi chút khác biệt. Nhìn chung, việc thực thi trên C# tương đối đơn giản so với các ngôn ngữ khác. Ngoài ra, các mẫu thiết kế có mức độ phức tạp khác nhau khi thực thi.

    Khi thực thi được mẫu thiết kế trên một ngôn ngữ bạn sẽ không gặp nhiều khó khăn khi chuyển sang một ngôn ngữ khác. Quan trọng là nắm được ý tưởng của mấu thiết kế đó.

    Phân loại Design pattern

    Như trên đã nói, có 23 mẫu thiết kế cổ điển chia làm 3 nhóm. Chúng ta sẽ điểm sơ qua các nhóm này để bạn có hình dung tổng quan về chúng.

    Structural pattern

    Structural pattern là những mẫu thiết kế có liên quan đến cách tổ hợp các class và object để tạo ra những cấu trúc lớn hơn. Ví dụ thêm tính năng (động) cho các object/class sẵn có, kiểm soát truy cập object, lựa chọn/thay đổi bản thực thi khi chạy chương trình, v.v.. Mỗi mẫu thiết kế trong nhóm sẽ có một/một số mục tiêu khác nhau.

    Dưới đây là tên gọi các pattern trong nhóm này:

    • Decorator
    • Proxy
    • Bridge
    • Composite
    • Flyweight
    • Adapter
    • Façade

    Creational pattern

    Creational pattern là những mẫu thiết kế liên quan đến việc tạo/tổ hợp/thể hiện object của class. Các mẫu này giúp tăng tính linh hoạt của hệ thống liên quan đến việc tạo object.

    Dưới đây là tên gọi các mẫu trong nhóm này:

    • Prototype
    • Factory Method
    • Singleton
    • Abstract Factory
    • Builder

    Behavioral pattern

    Behavioral pattern là những mẫu liên quan đến thuật toán và trao đổi thông tin.

    • Strategy
    • State
    • Template Method
    • Chain of Responsibility
    • Command
    • Iterator
    • Mediator
    • Observer
    • Visitor
    • Interpreter
    • Memento

    Các yêu cầu cho khóa học

    Đây là một khóa học nâng cao cho những bạn đã thành thạo lập trình C#. Bạn cần hiểu và vận dụng thành thạo các kỹ thuật lập trình hướng đối tượng như abstract class, inheritance, override, các kỹ thuật nâng cao của C# như delegate, interface, generic.

    Các ví dụ trong bài học hầu hết chỉ thực hiện trên giao diện console. Bạn có thể sử dụng .NET Framework hoặc .NET Core. Không có sự khác biệt nào khi sử dụng hai loại nền tảng này khi học. Tuy nhiên bạn không nên dùng các phiên bản C# quá cũ (trước 3.0) vì một số kỹ thuật đòi hỏi các tính năng của C# từ 3.0 trở lên.

    Các ví dụ được xây dựng và thử nghiệm trên Visual Studio 2019 (bản mới nhất hiện nay). Bạn có thể dùng các phiên bản khác (2015, 2017) hoặc Visual Studio Code.

    Bạn cũng lưu ý rằng, mặc dù có sự phân loại các mẫu thiết kế, giữa các mẫu thiết kế không có quan hệ rõ ràng chặt chẽ. Do đó bạn không cần học theo thứ tự. Tuy nhiên, các bài học trong tập bài giảng này sắp xếp các mẫu theo mức độ khó khi thực thi.

    Nếu bạn mới bắt đầu học C#, chúng tôi thành thực khuyên bạn chưa nên đọc tài liệu này. Bạn có thể tham khảo khóa học miễn phí “hướng dẫn tự học lập trình C#” trên site trước.

    Ngoài ra bạn còn cần đọc hiểu được sơ đồ class của UML. Chúng ta sẽ nhắc lại sơ lược một số thành phần quan trọng của UML thường gặp khi mô tả mẫu thiết kế.

    UML – Unified Modeling Language

    Khi học mẫu thiết kế bạn không thể không biết UML – ngôn ngữ mô hình hóa phổ biến nhất trong lĩnh vực phần mềm do tất cả các mẫu thiết kế đều được mô tả bằng một biểu đồ UML.

    Sơ đồ class trong UML

    Mặc dù bài giảng này không phải là một tài liệu về UML nhưng do sự quan trọng của ngôn ngữ này, chúng ta sẽ cùng xem lại một số thành phần quan trọng trong sơ đồ class của UML thường gặp trong tất cả các mô tả của các mẫu thiết kế.

    UML class diagram thường gặp trong mô tả design pattern

    Ở hình trên trình bày 3 loại block trong sơ đồ UML (class, interface/abstract class, package) và 5 loại quan hệ giữa chúng (Inheritance, Realization, Association, Aggregation, Composition). Đây là những phần tử thông dụng nhất sẽ gặp trong mọi mô tả mẫu thiết kế.

    Nếu chưa hiểu rõ UML, bạn hãy tìm đọc một số tài liệu cơ bản trước. Bạn cũng lưu ý chỉ cần đọc những nội dung về sơ đồ class. Trong UML có rất nhiều loại sơ đồ, bạn không cần biết hết để hiểu mô tả mẫu thiết kế.

    Ánh xạ UML class diagram sang C# code

    Khi làm việc với UML bạn sẽ phải hình dung ra cách “ánh xạ” từ sơ đồ UML sang code C# và ngược lại. Có một số điều lưu ý sau khi ánh xạ giữa sơ đồ UML và code:

    (1) Class của UML tương đương 1 – 1 với class của C#: các attribute của UML class diagram tương đương với biến thành viên của C# class; các operation của UML diagram tương đương với các phương thức hoặc property của C# class; các ký tự +, -, # lần lượt tương đương với từ khóa public, private và protected.

    (2) Interface của UML tương đương 1 – 1 với interface của C#. Lưu ý C# interface chỉ chứa định nghĩa phương thức và property nên UML interface hướng tới code C# chỉ nên chứa mô tả operation.

    (3) Package của UML có thể xem như tương đương với thư viện class (.dll) của C#, nơi nhóm các định nghĩa kiểu dữ liệu (class, interface) thành một đơn vị độc lập để tái sử dụng qua các project.

    (4) Note của UML có thể xem gần tương tự như ghi chú trong C#.

    (5) Inheritance của UML tương đương với kế thừa của C#. Lưu ý trong C# chỉ hỗ trợ đơn kế thừa. Đầu mũi tên là class cha, đuôi mũi tên là class con. Inheritance còn được gọi là quan hệ generalization (tổng quát hóa): class cha là tổng quát hóa của các class con; các class con là chi tiết hóa của lớp cha.

    (6) Realization hoặc implementation là quan hệ giữa interface và class thực thi interface đó. Khác biệt với kế thừa, trong C# một class có thể thực thi nhiều interface.

    (7) Association là quan hệ phổ biến nhất giữa các class, trong đó các class chứa object của nhau và truy xuất các biến, property, phương thức qua object.

    (8) Aggregation là một dạng đặc biệt của Association, còn gọi là quan hệ “has-a”. Trong quan hệ dưới đây, A chứa object của B nhưng object của B được truyền từ ngoài vào. Do đó B độc lập với A.

    (9) Composition có điểm tương tự như Aggregation nhưng mang tính phụ thuộc và cũng thường được gọi là quan hệ “part-of”. Trong sơ đồ ở trên, B được khởi tạo ở bên trong A, do đó nó là một phần của A đồng thời tồn tại phụ thuộc vào A.

    Theo dõi
    Thông báo của
    guest

    10 Thảo luận
    Cũ nhất
    Mới nhất
    Phản hồi nội tuyến
    Xem tất cả bình luận
    Dũng

    Bài viết hay lắm, cảm ơn tác giả nhé.

    Hoàng Long

    Mình nghĩ bạn nên đưa ví dụ cho từng Design Pattern sẽ hay hơn

    Thiện

    Trong .net core có bao nhiêu design pattern Admin?

    Linh Vu Hoang

    Bài viết gắn gọn, rõ ràng, nhấn vào các điểm chính. Mong chờ bài tiếp theo của tác giả.

    Lưu Đạt

    MỘT BÀI VIẾT TIẾNG VIỆT HAY NHẤT TỪNG ĐỌC

    Duy

    Bài viết rất chi tiết. Khi nào mới có bài mới vậy tác giả

    Nguyễn Hải Nam

    Cảm ơn bạn, trình bày rất dễ hiểu. Mong bạn sớm làm về observer pattern.

    Thuong Nguyen

    Series này hay quá, chị có thể tiếp tục ra bài mới không chị ?