Tổng Kết Design Patterns: 23 Pattern, 5 Bài Học
Tổng kết series Design Patterns A → Z trong C# / .NET 10: năm bài học sống sót, đọc gì tiếp, và mỗi pattern teo lại ra sao trong code hiện đại.
Mục lục
- Bài học 1 — pattern là từ vựng hay giải pháp?
- Bài học 2 — cái gì teo và cái gì sống?
- Bài học 3 — chi phí mọi pattern có thật không?
- Bài học 4 — bao nhiêu pattern framework đã cho sẵn?
- Bài học 5 — pattern kết hợp thành kiến trúc thế nào?
- Đọc gì tiếp sau series này?
- Ngày mai làm gì để giỏi hơn?
- Bài toán không vừa pattern nào thì sao?
- Đi tiếp đâu từ đây?
Bạn bắt đầu series tự hỏi sao người ta vẫn nói về design pattern ba mươi năm sau sách Gang of Four. Bạn kết thúc, hy vọng, với câu hỏi khác: pattern nào tôi sắp viết ở đây?. Sự chuyển đổi đó là cả lợi nhuận. Bài cuối ngắn có chủ đích — tổng kết, năm bài học, và list đọc gì sau cái này. Series ở lại, cuộc nói chuyện về codebase của bạn bắt đầu.
Bài học 1 — pattern là từ vựng hay giải pháp?
Gang of Four không phát minh ra pattern. Họ đặt tên chúng. Tám tên pattern mọi senior C# mang theo — Singleton, Factory Method, Adapter, Decorator, Strategy, Observer, Iterator, Command — là từ viết tắt năm-giây cho lựa chọn thiết kế từng cần một cuộc họp để thảo luận. Bản thân từ vựng là productivity gain.
Hệ quả rõ. Dùng pattern trong code mà không gọi tên trong comment là cơ hội bỏ lỡ. Reviewer không nên phải suy đoán bạn viết Decorator; tên class nên nói thế.
Bài học 2 — cái gì teo và cái gì sống?
Mọi pattern trong series có implementation 1994 và
implementation 2026. Bản 1994 là sơ đồ class; bản 2026 là một
hai dòng Program.cs. Inventory đầy đủ sống trong chương cây
quyết định — bản ngắn vừa
một thẻ:
- Record hấp thụ Builder, Prototype, Memento.
- DI hấp thụ Singleton, Factory Method, Abstract Factory, Strategy.
yieldhấp thụ Iterator.- Pattern matching hấp thụ Visitor.
event,IObservable<T>, vàChannel<T>hấp thụ Observer.- MediatR hấp thụ Mediator + Command.
- Middleware hấp thụ Chain of Responsibility.
- Framework hấp thụ Template Method (
BackgroundService,ControllerBase).
Hình pattern sống vì ý đồ cơ bản sống — "share một instance mỗi process", "swap thuật toán lúc runtime", "đi cấu trúc". Hình đổi theo ngôn ngữ; ý đồ không.
Bài học 3 — chi phí mọi pattern có thật không?
Series nói một lần mỗi chương và đáng nói lại. Mọi pattern thêm file, gián tiếp, và một tên người đọc tương lai phải học. Pattern kiếm tồn tại chỉ khi chi phí trả về — khi thêm tính năng không sửa code có sẵn, khi cô lập unit test, khi loại trùng lặp thật. Ba dấu hiệu bạn đang trả mà không kiếm:
- Một
Strategyvới một implementation. - Một
Decoratorkhông thêm gì. - Một
Facadeủy thác một method cho một collaborator.
Xoá trước; nâng cấp sau. Quy tắc của ba từ Giới thiệu là kỷ luật ngừa abstraction sớm.
Bài học 4 — bao nhiêu pattern framework đã cho sẵn?
Middleware ASP.NET Core là Chain of Responsibility. Proxy của
EF Core là Proxy. IEnumerable<T> là Iterator. record là
Prototype + Memento. Lazy<T> là Singleton. IComparer<T> là
Strategy. BackgroundService là Template Method.
Bạn học pattern để đọc code application. Lợi ích lớn nhất là
đọc code framework: khoảnh khắc bạn nhận ra app.Use((ctx, next) => ...) cùng hình với pipeline validate custom,
framework thôi là phép thuật. Các chương tham chiếu chéo các
kết nối này ở mọi khúc.
Bài học 5 — pattern kết hợp thành kiến trúc thế nào?
Mỗi chương so sánh một pattern với hai-ba sibling. Sự thật sâu hơn là mọi codebase thật compose pattern. Luồng checkout chúng ta dùng làm ví dụ xuyên suốt kết hợp:
- Singleton cho
PriceCatalog. - Factory Method cho
IPaymentProcessorchọn theo method. - Decorator cho log, retry, và fraud check quanh processor.
- Facade cho
CheckoutService. - Mediator cho notification
OrderPaid. - Command cho request
AddToCart,Checkout. - State cho lifecycle order.
- Strategy cho rule discount.
- Composite cho cart với bundle.
- Observer cho badge refresh khi cart đổi.
- Iterator cho mọi thứ bạn đi.
Mười một pattern trong một tính năng. Không cái nào là câu trả lời riêng; cùng nhau chúng là kiến trúc. Biết tên cho phép bạn mô tả kiến trúc đó trong một đoạn thay vì năm file source code. Hình dạng:
flowchart LR
Ctrl[CheckoutController] --> Facade[CheckoutService<br>Facade]
Facade --> Cart[Cart<br>Composite]
Facade --> Pay[IPaymentProcessor<br>Factory Method]
Pay --> Dec[Logging+Retry+FraudCheck<br>Decorator]
Facade --> State[Order<br>State machine]
Facade --> Mediator[IMediator<br>Mediator]
Mediator --> H1[ReserveInventory]
Mediator --> H2[SendEmail]
Mediator --> H3[Analytics]
State --> Strat[IDiscountStrategy<br>Strategy]
Cart --> Cat[PriceCatalog<br>Singleton]
Và trong C#, đăng ký nối mười một pattern đó nhỏ:
// Mười một pattern, một composition root
builder.Services.AddSingleton<IPriceCatalog, PriceCatalog>(); // Singleton
builder.Services.AddKeyedScoped<IPaymentProcessor, StripeProcessor>("stripe"); // Factory Method
builder.Services.Decorate<IPaymentProcessor, FraudCheckPaymentProcessor>(); // Decorator
builder.Services.Decorate<IPaymentProcessor, RetryingPaymentProcessor>();
builder.Services.Decorate<IPaymentProcessor, LoggingPaymentProcessor>();
builder.Services.AddScoped<ICheckoutService, CheckoutService>(); // Facade
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<Program>()); // Mediator + Command
builder.Services.AddKeyedSingleton<IDiscountStrategy, TieredDiscount>("tiered"); // Strategy
// State (entity Order) và Composite (cây Cart) là hình dạng, không phải đăng ký
Đọc gì tiếp sau series này?
Sách GoF 1994 vẫn đáng đọc một lần — cho từ vựng, không phải ví dụ C++. Sau đó:
- Robert C. Martin, Clean Architecture — nối tư duy mức pattern với biên module và rule dependency.
- Martin Fowler, Patterns of Enterprise Application Architecture — pattern trên mức GoF: Repository, Unit of Work, Service Layer, Domain Model.
- Martin Fowler, Refactoring — cách đến pattern từ code production thật.
- Microsoft Learn, Service lifetimes
— tham khảo chính thức cho
AddSingleton/AddScoped/AddTransient, là một nửa câu chuyện pattern .NET hiện đại. - refactoring.guru — giải thích visual sạch nhất mọi pattern GoF; tốt cho refresh mỗi chương.
- Source code ASP.NET Core, EF Core, và Roslyn — đây là demo scale-production của pattern. Đọc bất kỳ cái nào một buổi chiều và bạn sẽ thấy hình bạn học ở đây.
Ngày mai làm gì để giỏi hơn?
Năm thói quen nhỏ biến series thành kỹ năng vĩnh viễn:
- Đặt tên class theo pattern khi vừa.
PaymentProcessorAdapter,LoggingPaymentProcessor,OrderStateMachine. Tên là nửa giá trị. - Thêm comment một dòng khi pattern không hiển nhiên.
// Decorator: thêm idempotency quanh processor bên trong. - Review PR qua tên pattern. "Cái này muốn thành State, không phải Strategy." Dù bạn không push thay đổi, cuộc nói chuyện chặt hơn.
- Khi viết
if (type is X), dừng. Thường là Strategy hoặc Visitor giả dạng. Đôi khiifđúng; đôi khi là lần thứ ba và pattern vừa kiếm tồn tại. - Đọc lại một chương một tuần, sáu tuần. Series dài; nhận diện quan trọng hơn nhớ. Đọc lại giãn cách thắng đọc một lần anh hùng.
Bài toán không vừa pattern nào thì sao?
Bạn sẽ, đôi khi, thiết kế cái không vừa pattern nào trong 23. Ổn thôi. Pattern là hình phổ biến, không phải hình duy nhất. Khi bài toán thật sự mới, nước đi đúng là mô tả nó tốt — đặt tên cho nó, viết so sánh với các pattern nó không phải, tài liệu hoá ý đồ. Đó là cách pattern mới vào từ vựng từ đầu.
Pattern sống 30 năm vì programmer cứ tìm cùng vấn đề và đặt tên chia sẻ cho chúng. Bài học của series là bạn vừa tham gia cuộc nói chuyện đó. Người tiếp theo đọc code của bạn — có lẽ chính bạn sáu tháng sau — sẽ cảm ơn bạn vì từ vựng.
Đi tiếp đâu từ đây?
- Cây quyết định: Cách chọn design pattern phù hợp.
- Bắt đầu series: Giới thiệu.
- Điểm vào nhóm: Singleton (Creational), Adapter (Structural), Chain of Responsibility (Behavioral).
Cảm ơn bạn đã đọc series. Giờ đi mở một codebase production tôi nhắc và tìm pattern bạn nhận ra. Từ vựng giờ là của bạn để giữ.
Câu hỏi thường gặp
Đọc gì sau series này?
Có pattern nào mà sách GoF bỏ qua không?
IAsyncEnumerable, Channel<T>, async stream — gần như tương đương chương GoF mới. Danh sách 1994 là nền; cuộc nói chuyện vẫn tiếp.Làm sao tiếp tục giỏi hơn về design pattern sau series?
Takeaway lớn nhất từ học cả 23 pattern?
if/else bạn viết hôm qua thành 'một Strategy chờ xảy ra'. Cùng switch qua type thành 'state machine' hay 'visitor'. Đặt tên là nửa việc. Nửa kia là biết khi nào không áp pattern — đo bằng code có ngắn hơn, đơn giản hơn, dễ đổi hơn không. Không thì pattern đã sai.