[
  {
    "path": "README.md",
    "content": "# DESIGN PATTERN LÀ GÌ ?\n\n![design-pattern](./assets/design-patterns.png)\n\nDesign Pattern là một giải pháp tổng thể cho các vấn đề chung trong thiết kế phần mềm. Nó cũng tương tự các bản thiết kế cho xây dựng nhà cửa, chúng được dùng để giải quyết các vấn đề lặp đi lặp lại trong thiết kế của bạn.\n\nCác design pattern không thể copy rồi paste như cách bạn làm với các function có sẵn hay thư viện, vì chúng không phải là những đoạn code cụ thể. Design pattern ở đây là những khái niệm tổng quát để giải quyết các vấn đề riêng biệt. Bạn có thể tìm hiểu các design pattern và triển khai chúng lên ứng dụng của bạn. Các pattern thường bị nhầm lẫn với thuật toán, vì chúng đều là những khái niệm mô tả giải pháp cho một vấn đề nào đó. \n\nTrong khi thuật toán là định nghĩa những hành động cụ thể để giải quyết vấn đề thì design pattern lại là một mô tả cao hơn cho các giải pháp. Code cho cùng một pattern có thể được triển khai trên hai ứng dụng khác nhau.\n\n## Tài liệu design pattern bao gồm những gì ?\n\nHầu hết các tài liệu mô tả rất chính thống, để cho mọi người có thể tái sử dụng cho nhiều trường hợp. Dưới đây là các thành phần thường có trong các document mô tả pattern:\n\n- **Invention**: mục đích pattern, mô tả ngắn gọn cả vấn đề và giải pháp.\n- **Motivation**: giải thích thêm vấn đề và giải pháp mà mô hình khả thi.\n- **Structure**: cấu trúc của các lớp cho thấy từng phần của pattern và chúng có liên quan như thế nào.\n- **Example**: ví dụ bằng một trong những ngôn ngữ lập trình phổ biến giúp bạn dễ dàng nắm bắt ý tưởng đằng sau pattern.\n\n# Tại sao nên học design pattern\n\nSự thật là các lập trình viên có thể xoay xở làm việc trong nhiều năm mà không cần biết đến bất kỳ pattern nào. Rất nhiều người làm như vậy. Tuy nhiên, ngay cả trong trường hợp đó, bạn có thể đang triển khai một số pattern mà không hề hay biết. Vậy tại sao bạn lại dành thời gian tìm hiểu chúng?\n\n- Giúp sản phẩm của chúng ta linh hoạt, dễ dàng thay đổi và bảo trì hơn.\n- Có một điều luôn xảy ra trong phát triển phần mềm, đó là sự thay đổi về yêu cầu. Lúc này hệ thống phình to, các tính năng mới được thêm vào trong khi performance cần được tối ưu hơn.\n- Design pattern cung cấp những giải pháp đã được tối ưu hóa, đã được kiểm chứng để giải quyết các vấn đề trong software engineering. Các giải pháp ở dạng tổng quát, giúp tăng tốc độ phát triển phần mềm bằng cách đưa ra các mô hình test, mô hình phát triển đã qua kiểm nghiệm.\n- Những khi bạn gặp bất kỳ khó khăn đối với những vấn đề đã được giải quyết rồi, design patterns là hướng đi giúp bạn giải quyết vấn đề thay vì tự tìm kiếm giải pháp tốn kém thời gian.\n- Giúp cho các lập trình viên có thể hiểu code của người khác một cách nhanh chóng (có thể hiểu là các mối quan hệ giữa các module chẳng hạn). Mọi thành viên trong team có thể dễ dàng trao đổi với nhau để cùng xây dựng dự án mà không tốn nhiều thời gian.\n\n# Khi nào nên sử dụng design pattern\n\nViệc sử dụng các design pattern sẽ giúp chúng ta giảm được thời gian và công sức suy nghĩ ra các cách giải quyết cho những vấn đề đã có lời giải. Lợi ích của việc sử dụng các mô hình Design Pattern vào phần mềm đó chính là giúp chương trình chạy uyển chuyển hơn, dễ dàng quản lý tiến trình hoạt động, dễ nâng cấp bảo trì, …\n\nTuy nhiên điểm bất cập của design pattern là nó luôn là một lĩnh vực khá khó nhằn và hơi trừu tượng. Khi bạn viết code mới từ đầu, khá dễ dàng để nhận ra sự cần thiết phải có design pattern. Tuy nhiên, việc áp dụng design pattern cho code cũ thì khó khăn hơn.\n\nKhi sử dụng những design pattern có sẵn thì chúng ta sẽ đối mặt với một vấn đề nữa là perfomance của product (code sẽ chạy chậm chẳng hạn). Cần phải chắc chắn là bạn đã hiểu toàn bộ mã nguồn làm việc như thế nào trước khi đụng vào nó. Việc này có thể là dễ dàng hoặc là đau đầu, phụ thuộc vào độ phức tạp của code.\n\nHiện nay chúng ta đang áp dụng rất nhiều design pattern vào công việc lập trình của mình. Nếu bạn thường tải và cài đặt các thư viện, packages hoặc module nào đó thì đó là lúc bạn thực thi một design pattern vào hệ thống.\n\nTất cả các framework cho ứng dụng web như Laravel, Codeigniter… đều có sử dụng những kiến trúc design pattern có sẵn và mỗi framework sẽ có những kiểu design pattern riêng.\n\n# Phân loại design pattern\n\nHệ thống các design pattern được chia thành 3 nhóm: nhóm Creational, nhóm Structural và nhóm Behavioral.\n\n- [**Creational Pattern**](./creational-pattern) cung cấp các cơ chế tạo đối tượng để tăng tính linh hoạt và tái sử dụng mã hiện có.\n    + [**Factory Method**](./creational-pattern/factory-method)\n    + [**Abstract Factory**](./creational-pattern/abstract-factory)\n    + [**Builder**](./creational-pattern/builder)\n    + [**Prototype**](./creational-pattern/prototype)\n    + [**Singleton**](./creational-pattern/singleton)\n- [**Structural Pattern**](./structural-pattern) giải thích cách tập hợp các đối tượng và lớp thành các cấu trúc lớn hơn, trong khi vẫn giữ cho cấu trúc linh hoạt và hiệu quả.\n    + [**Adapter**](./structural-pattern/adapter)\n    + [**Bridge**](./structural-pattern/bridge)\n    + [**Composite**](./structural-pattern/composite)\n    + [**Decorator**](./structural-pattern/decorator)\n    + [**Facade**](./structural-pattern/facade)\n    + [**Flyweight**](./structural-pattern/flyweight)\n    + [**Proxy**](./structural-pattern/proxy)\n- [**Behavioral Pattern**](./behavioral-pattern) quan tâm đến việc giao tiếp hiệu quả và phân công nhiệm vụ giữa các đối tượng.\n    + [**Chain Of Responsibility**](./behavioral-pattern/chain-of-responsibility)\n    + [**Command**](./behavioral-pattern/command)\n    + [**Iterator**](./behavioral-pattern/iterator)\n    + [**Mediator**](./behavioral-pattern/mediator)\n    + [**Memento**](./behavioral-pattern/memento)\n    + [**Observer**](./behavioral-pattern/observer)\n    + [**State**](./behavioral-pattern/state)\n    + [**Strategy**](./behavioral-pattern/strategy)\n    + [**Template Method**](./behavioral-pattern/template-method)\n    + [**Visitor**](./behavioral-pattern/visitor)\n\n# Code Example\n\nCode ví dụ của RefactoringGuru\n\n| | Ngôn ngữ | Source Code |\n|-|----------|-------------|\n|![csharp](./assets/csharp.png)| C# | https://github.com/RefactoringGuru/design-patterns-csharp |\n|![cpp](./assets/cpp.png)| C++ | https://github.com/RefactoringGuru/design-patterns-cpp |\n|![go](./assets/go.png)| GO | https://github.com/RefactoringGuru/design-patterns-go |\n|![java](./assets/java.png)| JAVA | https://github.com/RefactoringGuru/design-patterns-java |\n|![php](./assets/php.png)| PHP | https://github.com/RefactoringGuru/design-patterns-php |\n|![python](./assets/python.png)| PYTHON | https://github.com/RefactoringGuru/design-patterns-python |\n|![ruby](./assets/ruby.png)| RUBY | https://github.com/RefactoringGuru/design-patterns-ruby |\n|![swift](./assets/swift.png)| SWIFT | https://github.com/RefactoringGuru/design-patterns-swift |\n|![typescript](./assets/typescript.png)| TYPESCRIPT | https://github.com/RefactoringGuru/design-patterns-typescript |\n\n\n# Nguồn\n\n## Sách \n\n![book](./assets/book.png)\n\n## Tác giả: [Refactoring.Guru](https://refactoring.guru)\n\n![author](./assets/author.png)"
  },
  {
    "path": "_config.yml",
    "content": "theme: jekyll-theme-tactile"
  },
  {
    "path": "behavioral-pattern/README.md",
    "content": "# Behavioral Design Pattern\n\nBehavioral Pattern quan tâm đến việc giao tiếp hiệu quả và phân công nhiệm vụ giữa các đối tượng.\n\n## Chain of Responsibility\n\n[![chain-of-responsibility](./assets/chain-of-responsibility-mini.png)](./chain-of-responsibility)\n\nCho phép bạn truyền các yêu cầu dọc theo một chuỗi xử lý. Khi nhận được yêu cầu, mỗi trình xử lý sẽ quyết định xử lý yêu cầu hoặc truyền nó cho trình xử lý tiếp theo trong chuỗi.\n\n## Command\n\n[![command](./assets/command-mini.png)](./command)\n\nBiến một yêu cầu thành một đối tượng độc lập bao gồm tất cả thông tin của yêu cầu đó. Chuyển đổi này giúp bạn truyền các yêu cầu dưới dạng tham số của phương thức, trì hoãn hoặc chờ đợi việc thực thi một yêu cầu hay hỗ trợ các hoạt động hoàn tác. \n\n## Iterator\n\n[![iterator](./assets/iterator-mini.png)](./iterator)\n\nDuyệt phần tử của một tập hợp mà không để lộ dạng cơ bản của nó (danh sách, ngăn xếp, cây, ...)\n\n## Mediator\n\n[![mediator](./assets/mediator-mini.png)](./mediator)\n\nGiúp bạn giảm các phụ thuộc hỗn tạp giữa các đối tượng. Pattern hạn chế các giao tiếp trực tiếp giữa các đối tượng và buộc nó giao tiếp thông qua đối tượng mediator.\n\n## Memento\n\n[![memento](./assets/memento-mini.png)](./memento)\n\nLưu và phục hồi trạng thái trước đó của một đối tượng mà không để lộ chi tiết triển khai của nó\n\n## Observer\n\n[![observer](./assets/observer-mini.png)](./observer)\n\nGiúp bạn định nghĩa một cơ chế đăng ký để thông báo cho nhiều đối tượng về bất kỳ sự kiện nào diễn ra với đối tượng mà chúng đang quan sát.\n\n## State\n\n[![state](./assets/state-mini.png)](./state)\n\nChỉnh sửa hành vi của một đối tượng khi trạng thái bên trong nó thay đổi. Nó xảy ra nếu như một đối tượng thay đổi lớp của nó.\n\n## Strategy\n\n[![strategy](./assets/strategy-mini.png)](./strategy)\n\nGiúp bạn xác định một nhóm thuật toán, đặt chúng vào một lớp riêng biệt và làm cho các đối tượng của chúng có thể hoán đổi lẫn nhau.\n\n## Template Method\n\n[![template-method](./assets/template-method-mini.png)](./template-method)\n\nĐịnh nghĩa bộ khung của thuật toán ở lớp cha (superclass) nhưng các lớp con (subsclasses) có thể ghi đè lên các bước cụ thể của thuật toán mà không làm thay đổi cấu trúc của nó.\n\n## Visitor\n\n[![visitor](./assets/visitor-mini.png)](./visitor)\n\nTách các thuật toán khỏi đối tượng mà chúng đang hoạt động trên đó.\n"
  },
  {
    "path": "behavioral-pattern/chain-of-responsibility/README.md",
    "content": "# Chain of Responsibility\n\n## 📜 Mục đích\n\n**Chain of Responsibility** là một design pattern trong nhóm behavioral cho phép bạn truyền các yêu cầu dọc theo một chuỗi xử lý. Khi nhận được yêu cầu, mỗi trình xử lý sẽ quyết định xử lý yêu cầu hoặc truyền nó cho trình xử lý tiếp theo trong chuỗi.\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nTưởng tượng bạn đang làm việc với hệ thống đặt hàng trực tuyến. Bạn muốn giới hạn truy cập đến hệ thống để chỉ những người dùng đã xác thực mới có thể đặt đơn hàng. Còn người quản trị viên (admin) có thể truy cập đến tất cả đơn hàng.\n\nSau khi lên kế hoạch, bạn nhận ra là các trình kiểm tra(check) phải làm việc liên tục. Vì ứng dụng có thể phải xác thực người dùng bất cứ khi nào hệ thống nhận về yêu cầu có kèm theo chứng thư của người dùng. Tuy nhiên, nếu chứng thư không hợp lệ và việc xác thực thất bại, thì sẽ không có bất kỳ trình kiểm tra nào khác xử lý nó.\n\n![problem1](./assets/problem1.png)\n\nTrong nhiều tháng tiếp theo, bạn đã phải triển khai rất nhiều các trình kiểm tra liên tục:\n- Một người đồng nghiệp đề nghị rằng sẽ không an toàn khi truyền dữ liệu thuần thẳng đến hệ thống. Bạn cần thêm một bước xác nhận tính hợp lệ của dữ liệu trong yêu cầu.\n- Sau đó, một ai đó nói rằng hệ thống của bạn dễ bị tấn công brute force để dò mật khẩu. Để tránh điều đó, bạn phải thêm một trình kiểm tra để lọc các yêu cầu thất bại lặp lại bởi cùng một địa chỉ IP.\n- Tiếp đến bạn có thêm đề nghị là nên tăng tốc hệ thống bằng cách sử dụng kết quả từ bộ đệm với những yêu cầu lặp lại cùng một dữ liệu. Do đó, bạn phải thêm tiếp một trình kiểm tra khác để chỉ truyền các yêu cầu đến hệ thống khi nó không phù hợp với phản hồi từ cache.\n\n![problem2](./assets/problem2.png)\n\nCode cho trình kiểm tra của bạn đã lộn xộn, giờ đây nó còn tệ hơn lúc trước khi bạn thêm các tính năng mới. Thay đổi một trình kiểm tra thỉnh thoảng sẽ ảnh hưởng lên cả những cái khác. Và tệ hơn nữa là khi bạn muốn dùng lại trình kiểm tra cho các bộ phận khác trong hệ thống, bạn phải sao chép một phần code vì bộ phận đó chỉ yêu cầu vài trình kiểm tra chứ không phải tất cả.\n\nHệ thống sẽ trở nên rất khó hiểu và khó hơn để bảo trì. Sau nhiều ngày đấu tranh với code bạn quyết định refactor tất cả mọi thứ.\n\n## 😊 Giải pháp\n\nGiống như các behavioral khác, **Chain of Responsibility** dựa trên việc chuyển đổi các hành vi riêng biệt thành các đối tượng độc lập được gọi là **handlers**. Trong trường hợp này, mỗi trình kiểm tra sẽ mở rộng các lớp của nó với một phương thức đơn nhất thực hiện công việc kiểm tra. Yêu cầu và dữ liệu của nó, được truyền đến phương thức này như là một tham số.\n\nPattern gợi ý bạn liên kết các handler thành một chuỗi(chain). Mỗi handler được liên kết có một trường cho lưu trữ tham chiếu đến handler kế tiếp trong chuỗi. Thêm vào đó, để xử lý một yêu cầu, handler truyền yêu cầu đến xa hơn theo chuỗi. Yêu cầu sẽ chạy khắp chuỗi cho đến khi tất cả handler có cơ hội xử lý nó.\n\nĐiều quan trọng ở đây: handler có thể quyết định không truyền yêu cầu sâu hơn trong chuỗi và dừng bất kỳ việc xử lý nào một cách hiệu quả.\n\nỞ ví dụ với hệ thống đặt hàng, một handler thực hiện xử lý sau đó quyết định truyền yêu cầu sâu hơn. Giả định yêu cầu bao gồm dữ liệu hợp lệ, tất cả handler có thể thực thi hành vi chính của nó, cho dù đó là kiểm tra xác thực hay bộ nhớ đệm.\n\n![solution1](./assets/solution1.png)\n\nTuy nhiên, có một cách tiếp cận khác nhẹ nhàng hơn (và chuẩn hơn), mỗi khi nhận được yêu cầu, một handler quyết định liệu nó có thể xử lý hay không. Nếu nó có thể, sẽ không phải truyền yêu cầu xa hơn. Thế nên, sẽ chỉ có một handler để xử lý yêu cầu hoặc không có cái nào cả. Cách tiếp cận này rất giống với xử lý sự kiện trong ngăn xếp phần tử ở giao diện đồ hoạ người dùng.\n\nVí dụ, khi người dùng click một button, sự kiện sẽ truyền đến chuỗi phần tử GUI, bắt đầu với button, tiếp đến là container(có thể là form hoặc panel) và kết thúc ở của sổ chính của ứng dụng. Sự kiện sẽ được xử lý ở phần tử đầu tiên trong chuỗi có thể xử lý nó. Ví dụ này đáng lưu tâm vì nó cho thấy một chuỗi có thể mở rộng từ một đối tượng cây.\n\n![solution2](./assets/solution2.png)\n\nĐiều quan trọng là tất cả lớp handler phải triển khai cùng interface. Mỗi handler cụ thể chỉ nên quan tâm một thứ theo sau phương thức thực thi. Cách này giúp bạn có thể tạo chuỗi khi đang chạy, sử dụng handler khác nhau mà không cần ghép code với lớp cụ thể của nó.\n\n## 🚗 Thế Giới Thực\n\nBạn vừa mua và cài đặt một vài phần cứng mới lên máy tính của bạn. Ví lý do cá nhân, nên máy tính bạn có nhiều hệ điều hành. Bạn thử boot tất cả và xem phần cứng có được hỗ trợ không. Window nhận ra nó và tự động enable phần cứng. Nhưng, Linux yêu dấu của bạn lại từ chối làm việc với phần cứng mới. Bất lực, bạn quyết định gọi đến số điện thoại hỗ trợ khi mua phần cứng.\n\nThứ đầu tiên mà bạn nghe là giọng robot phản hồi tự động. Nó đề nghị các giải pháp phổ biến với nhiều vấn đề khác nhau nhưng không cái nào liên quan đến trường hợp của bạn. Sau đấy, robot kết nối bạn với nhà điều hành trực tiếp.\n\nXui xẻo, nhà điều hành cũng không thể đề xuất được điều gì cụ thể. Anh ta cứ nói theo hướng dẫn sử dụng, và không chịu lắng nghe bạn. Sau khi nghe: \"bạn đã thử tắt máy và bật lại chưa\" khoảng 10 lần, bạn đề nghi kết nối đến kỹ sư thích hợp.\n\nSau cùng, nhà điều hành chuyển cuộc gọi của bạn đến kỹ sư, một người có lẽ khao khát được nói chuyện trực tiếp với con người hàng giờ khi anh ta ngồi cô đơn trong phòng server ở một hầm tối nào đó trong toà nhà nào đó. Kỹ sư nói với bạn nơi tải về drive thích hợp cho phần cứng của bạn và cách cài đặt nó trên Linux. Cuối cùng vấn đề được giải quyết. \n\n![analogy](./assets/analogy.png)\n\n## 🏢 Cấu trúc\n\n![structure](./assets/structure.png)\n\n1. **Handler** khai báo interface chung cho tất cả concrete handler. Nó thường chỉ bao gồm một phương thức đơn nhất cho tất cả yêu cầu xử lý, nhưng thỉnh thoảng nó có thể chứa phương thức khác cho cài đặt handler tiếp theo trong chuỗi.\n2. **Base Handler** là lớp tuỳ chọn, nơi bạn có thể đặt code mẫu vào tất cả lớp handler.\nThông thường, lớp này định nghĩa một trường lưu trữ tham chiếu đến handler kế tiếp. Client có thể tạo chuỗi bằng cách truyền handler đến hàm khởi tạo hoặc setter của handler trước đó. \n\n    Lớp còn có thể triển khai các xử lý mặc định: nó có thể truyền thực thi sang handler tiếp theo sau khi kiểm tra sự tồn tại của nó.\n3. **Concrete Handler** bao gồm đoạn code thực cho yêu cầu xử lý. Khi nhận yêu cầu, mỗi handler phải quyết định xử lý nó hoặc truyền nó dọc theo chuỗi.\nHandler thường là khép kín và bất biến, nhận mỗi dữ liệu cần thiết chỉ một lần thông qua hàm khởi tạo.\n4. **Client** có thể tạo chuỗi chỉ một lần hoặc tạo động, dựa trên logic của ứng dụng. Lưu ý yêu cầu có thể được gửi đến bất kỳ handler nào trong chuỗi, không nhất thiết phải là đầu tiên.\n\n## 👨‍💻 Mã giả\n\nTrong ví dụ này, Chain of Responsibility chịu trách nhiệm hiển thị thông tin trợ giúp cho người dùng theo ngữ cảnh ở các phần tử GUI đang hoạt động.\n\n![pseudocode](./assets/pseudocode.png)\n\nỨng dụng GUI thường có cấu trúc là một đối tượng cây. Ví dụ, lớp `Dialog`, thứ sẽ hiển thị cửa sổ chính của ứng dụng, sẽ là *root* của đối tượng cây. Dialog bao gồm `Panels`, sẽ chứa những panel khác hoặc phần tử đơn giản hơn như `Button` hay `TextFields`.\n\nMột phần tử đơn giản có thể hiển thị `tooltips` theo ngữ cảnh dễ dàng, miễn là thành phần đó có một số văn bản trợ giúp được chỉ định. Nhưng các thành phần phức tạp hơn xác định cách riêng của chúng để hiển thị trợ giúp theo ngữ cảnh, chẳng hạn như hiển thị đoạn trích từ sách hướng dẫn hoặc mở trong trình duyệt.\n\n![pseudocode2](./assets/pseudocode2.png)\n\nKhi người dùng click vào một phần tử và nhấn phím `F1`, ứng dụng sẽ xác định thành phần được click và gửi yêu cầu trợ giúp. Yêu cầu chạy qua tất cả các container của phần tử cho đến khi đến được phần tử có khả năng hiển thị thông tin trợ giúp.\n\n```c\n// Interface handler khai báo một phương thức cho tạo chuỗi\n// handler. Nó còn khai báo một phương thức thực thi yêu cầu.\ninterface ComponentWithContextualHelp is\n    method showHelp()\n\n\n// Lớp cơ sở cho các thành phần đơn giản.\nabstract class Component implements ComponentWithContextualHelp is\n    field tooltipText: string\n\n    // Thành phần của container hành độn như một liên kết \n    // tiếp theo trong chuỗi handler.\n    protected field container: Container\n\n    // Thành phần hiển thị tooltip nếu nó có văn bản trợ giúp\n    // được chỉ định cho nó. Nếu không nó chuyển tiếp cuộc gọi\n    // đến container.\n    method showHelp() is\n        if (tooltipText != null)\n            // Hiển thị tooltip.\n        else\n            container.showHelp()\n\n\n// Container có thể bao gồm thành phần đơn giản hoặc container khác.\n// Chuỗi quan hệ được thiết lập ở đây. Lớp kế thừa hành vi `showHelp`\n// từ cha của nó.\nabstract class Container extends Component is\n    protected field children: array of Component\n\n    method add(child) is\n        children.add(child)\n        child.container = this\n\n\n// Thành phần nguyên thuỷ có thể ổn với triển khai\n// trợ giúp mặc định...\nclass Button extends Component is\n    // ...\n\n\n// Nhưng với thành phần phức tạp, nó có thể ghi đè triển khai mặc\n// định. Nếu văn bản trợ giúp không thể được cung cấp theo cách mới, \n// thành phần có thể gọi triển khai cơ sở (xem lớp Component).\nclass Panel extends Container is\n    field modalHelpText: string\n\n    method showHelp() is\n        if (modalHelpText != null)\n            // Hiển thị cửa sổ modal với văn bản trợ giúp.\n        else\n            super.showHelp()\n\n// ...giống như trên...\nclass Dialog extends Container is\n    field wikiPageURL: string\n\n    method showHelp() is\n        if (wikiPageURL != null)\n            // Hiển thị trang wiki trợ giúp.\n        else\n            super.showHelp()\n\n\n// Code ở client.\nclass Application is\n    // Mọi ứng dụng cấu hình chuỗi khác nhau.\n    method createUI() is\n        dialog = new Dialog(\"Budget Reports\")\n        dialog.wikiPageURL = \"http://...\"\n        panel = new Panel(0, 0, 400, 800)\n        panel.modalHelpText = \"This panel does...\"\n        ok = new Button(250, 760, 50, 20, \"OK\")\n        ok.tooltipText = \"This is an OK button that...\"\n        cancel = new Button(320, 760, 50, 20, \"Cancel\")\n        // ...\n        panel.add(ok)\n        panel.add(cancel)\n        dialog.add(panel)\n\n    // Hãy tưởng tượng điều gì xảy ra ở đây.\n    method onF1KeyPress() is\n        component = this.getComponentAtMouseCoords()\n        component.showHelp()\n```\n\n## 💡 Ứng dụng\n**🐞 Sử dụng Chain of Responsibility khi chương trình của bạn phải xử lý các loại yêu cầu khác nhau bằng nhiều cách khác nhau, nhưng kiểu yêu cầu chính xác và trật tự của nó thì không biết trước.**\n\n⚡ CoR giúp bạn liên kết nhiều handler thành một chuỗi và khi nhận yêu cầu, sẽ \"hỏi\" mỗi handler có thể xử lý nó không. Cách này giúp tất cả handler có cơ hội xử lý yêu cầu.\n\n**🐞 Sử dụng CoR khi nó là thiết yếu để thực thi nhiều handler trong một trật tự cụ thể**\n\n⚡ Vì bạn có thể liên kết các handler trong chuỗi theo bất kỳ thứ tự nào, tất cả yêu cầu có thể đi qua chuỗi theo chính xác những gì bạn định ra.\n\n**🐞 Sử dụng CoR khi tập hợp handler và thứ tự của chúng thay đổi theo thời gian**\n\n⚡ Nếu bạn cung cấp setter cho trường tham chiếu trong lớp handler, bạn có thể chèn, xoá hoặc thay đổi thứ tự handler.\n\n## 📋 Triển khai\n\n1. Khai báo interface handler và mô tả signature của một phương thức để xử lý các yêu cầu.\n    Quyết định cách client sẽ truyền dữ liệu yêu cầu vào phương thức. Cách linh hoạt nhất là chuyển yêu cầu thành một đối tượng và chuyển nó đến phương thức xử lý dưới dạng một tham số.\n\n2. Để loại bỏ code mẫu trùng lặp trong concrete handler, cần tạo một lớp handler cơ sở trừu tượng, bắt nguồn từ interface handler.\n\n    Lớp này phải có một trường để lưu trữ một tham chiếu đến handler tiếp theo trong chuỗi. Xem xét việc làm cho lớp trở nên bất biến. Tuy nhiên, nếu bạn định sửa đổi chuỗi trong thời gian chạy, bạn cần xác định một setter để thay đổi giá trị của trường tham chiếu.\n\n    Bạn cũng có thể triển khai hành vi mặc định thuận tiện cho phương pháp xử lý, đó là chuyển tiếp yêu cầu đến đối tượng tiếp theo trừ khi không còn đối tượng nào. Các concrete handler có thể sử dụng hành vi này bằng cách gọi phương thức cha.\n\n3. Từng cái một tạo các lớp con của concrete handler và thực hiện các phương pháp xử lý của chúng. Mỗi handler phải đưa ra hai quyết định khi nhận được yêu cầu:\n    - Liệu nó có xử lý yêu cầu hay không.\n    - Liệu nó có chuyển yêu cầu theo chuỗi hay không.\n\n4. Client có thể tự lắp ráp chuỗi hoặc nhận chuỗi được tạo sẵn từ các đối tượng khác. Trong trường hợp sau, bạn phải triển khai một số lớp factory để xây dựng chuỗi theo cấu hình hoặc cài đặt môi trường.\n\n5. Client có thể kích hoạt bất kỳ handler nào trong chuỗi, không chỉ handler đầu tiên. Yêu cầu sẽ được chuyển dọc theo chuỗi cho đến khi một số handler từ chối chuyển thêm hoặc cho đến khi nó đến cuối chuỗi.\n\n6. Do tính chất động của chuỗi, client nên sẵn sàng xử lý các tình huống sau:\n    - Chuỗi có thể bao gồm một liên kết duy nhất.\n    - Một số yêu cầu có thể không đến cuối chuỗi.\n    - Những yêu cầu khác có thể đến cuối chuỗi không được xử lý.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ Bạn có thể kiểm soát thứ tự xử lý yêu cầu.\n\n✔️ *Single Responsibility Principle*. Bạn có thể tách các lớp gọi hoạt động từ các lớp thực hiện hoạt động.\n\n✔️ *Open/Closed Principle*. Bạn có thể thêm handler mới vào ứng dụng mà không ảnh hưởng đến code client hiện có.\n\n### Nhược điểm\n\n❌ Một số yêu cầu có thể không được giải quyết.\n\n## 🔁 Quan hệ với các pattern khác\n\n**Chain of Responsibility**, **Command**, **Mediator** và **Observer** giải quyết các cách khác nhau để kết nối người gửi và người nhận yêu cầu:\n\n- **CoR** chuyển một yêu cầu tuần tự dọc theo một chuỗi động gồm những người nhận tiềm năng cho đến khi một trong số họ xử lý nó.\n- **Command** thiết lập các kết nối một chiều giữa người gửi và người nhận.\n- **Mediator** loại bỏ các kết nối trực tiếp giữa người gửi và người nhận, buộc họ phải giao tiếp gián tiếp thông qua một đối tượng trung gian.\n- **Observer** cho phép người nhận đăng ký động và hủy đăng ký nhận yêu cầu. \n\n**Chain of Responsibility** thường được sử dụng cùng với **Composite**. Trong trường hợp này, khi một thành phần leaf nhận được một yêu cầu, nó có thể chuyển nó qua chuỗi của tất cả các thành phần mẹ xuống gốc của cây đối tượng.\n\nHandler trong **Chain of Responsibility** có thể triển khai như **Command**. Trong trường hợp này bạn có thể thực thi các hành động khác nhau trên cùng một đối tượng ngữ cảnh, được biểu diễn bởi yêu cầu.\n\nTuy nhiên, có cách tiếp cận khác, khi bản thân yêu cầu là một đối tượng **Command**. Trong trường hợp này bạn có thể thực thi cùng một hành động trên một loạt các ngữ cảnh khác nhau được liên kết thành một chuỗi.\n\n**Chain of Responsibility** và **Decorator** có cấu trúc lớp rất giống nhau. Cả hai pattern đều dựa vào thành phần đệ quy để truyền việc thực thi qua một loạt các đối tượng. Tuy nhiên, có một số khác biệt quan trọng.\n\nCác handler trong **CoR** có thể thực hiện các hoạt động tùy ý độc lập với nhau. Nó cũng có thể ngừng chuyển yêu cầu thêm vào bất kỳ lúc nào. Mặt khác, các **Decorator** khác nhau có thể mở rộng hành vi của đối tượng trong khi vẫn giữ cho nó nhất quán với interface cơ sở. Ngoài ra, **Decorator** không được phép phá vỡ quy trình của yêu cầu.\n\n# Nguồn\n\n[refactoring](https://refactoring.guru/design-patterns/chain-of-responsibility)\n"
  },
  {
    "path": "behavioral-pattern/command/README.md",
    "content": "# Command\n\n## 📜 Mục đích\n\n**Command** là một design pattern thuộc nhóm behavioral, nó biến một yêu cầu thành một đối tượng độc lập bao gồm tất cả thông tin của yêu cầu đó. Chuyển đổi này giúp bạn truyền các yêu cầu dưới dạng tham số của phương thức, trì hoãn hoặc chờ đợi việc thực thi một yêu cầu hay hỗ trợ các hoạt động hoàn tác. \n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nTưởng tượng bạn đang làm việc với một ứng dụng soạn thảo văn bản. Công việc hiện tại của bạn là tạo một thanh công cụ với nhóm button cho các thao tác khác nhau của editor. Bạn đã tạo một lớp `Button` gọn gàng để có thể dùng cho các button khác của thanh công cụ, cũng như cho các button chung ở các cửa sổ khác.\n\n![problem1](./assets/problem1.png)\n\nTrong khi tất cả button này trông giống nhau, thì chúng lại hỗ trợ những công việc khác nhau. \n\nVậy bạn sẽ đặt code cho các xử lý thao tác click khác nhau của chúng ở đâu ? Giải pháp đơn giản nhất là tạo hàng nghìn lớp con cho từng nơi mà button được sử dụng. Các lớp con này sẽ bao gồm code cho thực thi thao tác click.\n\n![problem2](./assets/problem2.png)\n\nRất nhanh chóng, bạn nhận ra cách tiếp cận này tồn đọng rất nhiều thiếu sót. Đầu tiên, bạn sẽ có một số lượng rất lớn lớp con, và nó sẽ không ổn khi bạn sửa đổi lớp `Button` cơ sở vì bạn phải thay đổi tất cả các lớp con của nó. Nói một cách đơn giản, code GUI của bạn đã trở nên phụ thuộc một cách khó hiểu vào những đoạn code dễ thay đổi của logic nghiệp vụ. \n\n![problem3](./assets/problem3.png)\n\nVà phần tồi tệ hơn ở đây. Một vài thao tác như copy/paste, sẽ cần được gọi từ rất nhiều nơi. Ví dụ, người dùng có thể click vào button \"Copy\" trên thanh công cụ, hoặc thực hiện thông quan menu hay chỉ đơn giản là Ctrl+C trên bàn phím.\n\nBan đầu, khi ứng dụng của bạn chỉ có một thanh công cụ, có thể đặt việc triển khai các hoạt động khác nhau vào các lớp con của button. Nói cách khác, ta có code để sao chép văn bản bên trong lớp con `CopyButton`. Nhưng sau đó, khi bạn triển khai menu, lối tắt và những thứ khác, bạn phải sao chép code của thao tác trong nhiều lớp hoặc làm cho menu phụ thuộc vào các button, mọi thứ sẽ trở nên tệ hoặc tệ hơn nữa.\n\n## 😊 Giải pháp\n\nMột thiết kế phần mềm tốt thường dựa trên *nguyên tắc tách biệt các mối quan tâm*, điều này thường dẫn đến việc chia ứng dụng thành nhiều lớp. Ví dụ phổ biến nhất: một lớp cho giao diện người dùng đồ họa và một lớp khác cho logic nghiệp vụ. Lớp GUI chịu trách nhiệm hiển thị hình ảnh đẹp mắt trên màn hình, thu nhận bất kỳ đầu vào nào và hiển thị kết quả về những gì người dùng và ứng dụng đang làm. Tuy nhiên, khi cần làm điều gì đó quan trọng, như tính toán quỹ đạo của mặt trăng hoặc soạn báo cáo hàng năm, lớp GUI sẽ ủy quyền công việc cho lớp logic nghiệp vụ cơ bản.\n\nTrong đoạn code, nó có thể trông như thế này: một đối tượng GUI gọi một phương thức của đối tượng logic nghiệp vụ, truyền cho nó một số tham số. Quá trình này thường được mô tả như một đối tượng gửi một yêu cầu khác.\n\n![solution1](./assets/solution1.png)\n\nCommand gợi ý rằng các đối tượng GUI không nên gửi trực tiếp các yêu cầu này. Thay vào đó, bạn nên trích xuất tất cả các chi tiết yêu cầu, chẳng hạn như đối tượng được gọi, tên của phương thức và danh sách các đối số vào một lớp command riêng biệt với một phương thức kích hoạt yêu cầu này.\n\nCác đối tượng command đóng vai trò là liên kết giữa các đối tượng GUI và logic nghiệp vụ khác nhau. Từ bây giờ, đối tượng GUI không cần biết đối tượng logic nghiệp vụ nào sẽ nhận được yêu cầu và cách xử lý yêu cầu. Đối tượng GUI chỉ cần kích hoạt command, nó sẽ xử lý tất cả các chi tiết.\n\n![solution2](./assets/solution2.png)\n\nBước tiếp theo là làm cho các command của bạn triển khai cùng một interface. Thông thường nó chỉ có một phương thức thực thi duy nhất mà không cần tham số. Interface này cho phép bạn sử dụng các command khác nhau với cùng một người gửi yêu cầu mà không cần kết hợp nó với các lớp command cụ thể. Như vậy, giờ đây bạn có thể chuyển đổi các đối tượng command được liên kết với người gửi, hay thay đổi một cách hiệu quả hành vi của người gửi trong thời gian chạy.\n\nBạn có thể nhận thấy một phần còn thiếu của vấn đề, đó là các tham số yêu cầu. Một đối tượng GUI có thể đã cung cấp cho đối tượng lớp nghiệp vụ một số tham số. Vì phương thức thực thi của command không có bất kỳ tham số nào, như vậy chúng ta sẽ chuyển các chi tiết yêu cầu đến người nhận như thế nào? Hóa ra command phải được cấu hình trước với dữ liệu này hoặc có khả năng tự lấy nó.\n\n![solution3](./assets/solution3.png)\n\nHãy quay lại trình soạn thảo văn bản. Sau khi áp dụng Command, ta không còn cần đến tất cả các lớp con của button đó để thực hiện các hành vi click chuột khác nhau. Chỉ cần đặt một trường vào lớp `Button` cơ sở là đủ để lưu trữ tham chiếu đến đối tượng command và làm cho button thực hiện command đó khi click chuột.\n\nBạn sẽ triển khai một loạt các lớp command cho mọi hoạt động có thể và liên kết chúng với các button cụ thể, tùy thuộc vào hành vi dự kiến của các button.\n\nCác phần tử GUI khác, chẳng hạn như menu, lối tắt hoặc toàn bộ hộp thoại, có thể được thực hiện theo cách tương tự. Chúng sẽ được liên kết với một command được thực thi khi người dùng tương tác với phần tử GUI. Như bạn có thể đoán bây giờ, các phần tử liên quan đến các hoạt động giống nhau sẽ được liên kết với các command giống nhau, ngăn chặn bất kỳ sự trùng lặp code nào.\n\nKết quả là, các command trở thành một lớp trung gian thuận tiện giúp giảm sự ghép nối giữa GUI và các lớp logic nghiệp vụ. Và đó chỉ là một phần nhỏ trong số những lợi ích mà Command có thể mang lại!\n\n## 🚗 Thế Giới Thực\n\n![analogy](./assets/analogy.png)\n\nSau khi đi bộ qua thành phố, bạn đến một nhà hàng sang trọng và ngồi vào bàn bên cửa sổ. Một người phục vụ thân thiện tiếp cận bạn và nhận đơn đặt hàng của bạn, viết nó ra một tờ giấy. Người phục vụ đi vào bếp và dán thứ tự lên tường. Sau một thời gian, đơn đặt hàng được chuyển đến đầu bếp, người sẽ đọc và nấu bữa ăn cho phù hợp. Người đầu bếp đặt bữa ăn vào khay cùng với thứ tự. Người phục vụ lấy khay, kiểm tra thứ tự để đảm bảo mọi thứ đều như bạn muốn và mang mọi thứ đến bàn của bạn.\n\nTrật tự trên giấy dùng như một command. Nó vẫn còn trong hàng đợi cho đến khi đầu bếp sẵn sàng phục vụ nó. Đơn đặt hàng chứa tất cả các thông tin liên quan cần thiết để nấu bữa ăn. Nó cho phép đầu bếp bắt đầu nấu ăn ngay lập tức thay vì chạy xung quanh để làm rõ chi tiết đơn đặt hàng trực tiếp từ bạn.\n\n## 🏢 Cấu trúc\n\n![structure](./assets/structure.png)\n\n1. **Sender** (hay còn gọi là invoker) là lớp chịu trách nhiệm khởi tạo các yêu cầu. Lớp này phải có một trường để lưu trữ một tham chiếu đến một đối tượng command. Sender(người gửi) kích hoạt command đó thay vì gửi yêu cầu trực tiếp đến receiver(người nhận). Lưu ý rằng sender không chịu trách nhiệm tạo đối tượng command. Thông thường, nó nhận một command được tạo trước từ client thông qua phương thức khởi tạo.\n2. **Command** là interface, thường khai báo một phương thức đơn nhất để thực hiện lệnh.\n3. **Concrete Command** thực hiện nhiều loại yêu cầu khác nhau. Một command cụ thể không được phép tự thực hiện công việc, mà chỉ chuyển lệnh gọi đến một trong các đối tượng logic nghiệp vụ. Tuy nhiên, để đơn giản hóa code, các lớp này có thể được hợp nhất.\n\n    Các tham số cần thiết để thực thi một phương thức trên một đối tượng nhận có thể được khai báo dưới dạng các trường trong concrete command. Bạn có thể làm cho các đối tượng command trở nên bất biến bằng cách chỉ cho phép khởi tạo các trường này thông qua phương thức khởi tạo.\n4. **Receiver** là lớp chứa một số logic nghiệp vụ. Hầu như bất kỳ đối tượng nào cũng có thể hoạt động như một receiver. Hầu hết các command chỉ xử lý các chi tiết về cách một yêu cầu được chuyển đến receiver, trong khi receiver phải tự thực hiện công việc thực tế.\n5. **Client** tạo và cấu hình các đối tượng command cụ thể. Client phải chuyển tất cả các tham số yêu cầu, bao gồm cả sender, vào phương thức khởi tạo của command. Sau đó, command kết quả có thể được liên kết với một hoặc nhiều receiver.\n\n## 👨‍💻 Mã giả\n\nTrong ví dụ này, Command giúp bạn theo dõi lịch sử các thao tác thực thi và hoàn tác nó nếu cần thiết.\n\n![pseudocode](./assets/pseudocode.png)\n\nCommand dẫn đến các thay đổi trạng thái của editor (sao chép, cắt, dán) sẽ tạo bản sao lưu trạng thái của editor trước khi thực thi một thao tác liên kết với command. Sau khi command thực thi, nó lưu vào lịch sử command(một ngăn xếp các đối tượng command) cùng với bản sao lưu trạng thái của editor tại thời điểm đó. Sau đó, nếu người dùng cần hoàn tác một hành động, ứng dụng có thể lấy command gần nhất từ lịch sử, đọc bản sao liên kết với trạng thái của editor và phục hồi nó.\n\nCode client (phần tử GUI, lịch sử command) không phải ghép với lớp command cụ thể bởi vì nó hoạt động với command thông qua interface command. Cách tiếp cận này giúp bạn thêm command mới vào ứng dụng mà không ảnh hưởng gì đến code hiện có.\n\n```c\n// Lớp command cơ sở xác định interface chung cho tất cả\n// concrete command.\nabstract class Command is\n    protected field app: Application\n    protected field editor: Editor\n    protected field backup: text\n\n    constructor Command(app: Application, editor: Editor) is\n        this.app = app\n        this.editor = editor\n\n    // Tạo một bản sao lưu trạng thái editor.\n    method saveBackup() is\n        backup = editor.text\n\n    // Phục hồi trạng thái editor.\n    method undo() is\n        editor.text = backup\n\n    // Phương thức thực thi khai báo trừu tượng cho tất cả\n    // concrete command tạo các triển khai của riêng nó.\n    // Phương thức trả về true hoặc false tuỳ thuộc vào command\n    // có thay đổi trạng thái editor hay không.\n    abstract method execute()\n\n\n// Concrete command ở đây.\nclass CopyCommand extends Command is\n    // Bản sao command không được lưu vào lịch sử vì nó\n    // không thay đổi trạng thái editor.\n    method execute() is\n        app.clipboard = editor.getSelection()\n        return false\n\nclass CutCommand extends Command is\n    // Command cut thay đổi trạng thái editor, do đó nó phải\n    // được lưu vào lịch sử. Và nó sẽ được lưu miễn là \n    // phương thức trả về true.\n    method execute() is\n        saveBackup()\n        app.clipboard = editor.getSelection()\n        editor.deleteSelection()\n        return true\n\nclass PasteCommand extends Command is\n    method execute() is\n        saveBackup()\n        editor.replaceSelection(app.clipboard)\n        return true\n\n// Thao tác undo cũng là command.\nclass UndoCommand extends Command is\n    method execute() is\n        app.undo()\n        return false\n\n\n// Lịch sử command chỉ là một ngăn xếp.\nclass CommandHistory is\n    private field history: array of Command\n\n    // Last in...\n    method push(c: Command) is\n        // Thêm command vào cuối của mảng lịch sử.\n\n    // ...first out\n    method pop():Command is\n        // Lấy command gần nhất khỏi lịch sử.\n\n\n// Lớp editor thực hiện các thao tác thực. Nó hoạt động như\n// một receiver: tất cả command uỷ thác thực thi cho phương\n// thức của editor.\nclass Editor is\n    field text: string\n\n    method getSelection() is\n        // Trả về văn bản được chon.\n\n    method deleteSelection() is\n        // Xoá văn bản được chon.\n\n    method replaceSelection(text) is\n        // Chèn nội dung của clipboard vào vị trí hiện tại.\n\n// Lóp ứng dụng thiết lập quan hệ đối tượng. Nó hành động như \n// một sender: khi điều gì đó cần hoàn thành, nó tạo đối tượng\n// command và thực thi nó.\nclass Application is\n    field clipboard: string\n    field editors: array of Editors\n    field activeEditor: Editor\n    field history: CommandHistory\n\n    // Đoạn code gán command cho các đối tượng UI \n    // có thể trông như thế này.\n    method createUI() is\n        // ...\n        copy = function() { executeCommand(\n            new CopyCommand(this, activeEditor)) }\n        copyButton.setCommand(copy)\n        shortcuts.onKeyPress(\"Ctrl+C\", copy)\n\n        cut = function() { executeCommand(\n            new CutCommand(this, activeEditor)) }\n        cutButton.setCommand(cut)\n        shortcuts.onKeyPress(\"Ctrl+X\", cut)\n\n        paste = function() { executeCommand(\n            new PasteCommand(this, activeEditor)) }\n        pasteButton.setCommand(paste)\n        shortcuts.onKeyPress(\"Ctrl+V\", paste)\n\n        undo = function() { executeCommand(\n            new UndoCommand(this, activeEditor)) }\n        undoButton.setCommand(undo)\n        shortcuts.onKeyPress(\"Ctrl+Z\", undo)\n\n    // Thực thi command và kiểm tra xem nó có phải thêm vào lịch sử\n    // hay không.\n    method executeCommand(command) is\n        if (command.execute)\n            history.push(command)\n\n    // Lấy command gần nhất khởi lịch sử và chạy phương thức undo.\n    // Lưu ý ta không biết lớp của command này. Nhưng ta không cần\n    // phải biết, vì command biết cách phải thực hiện hành động undo.\n    method undo() is\n        command = history.pop()\n        if (command != null)\n            command.undo()\n```\n\n## 💡 Ứng dụng\n\n**🐞 Sử dụng Command khi bạn muốn tham số hoá đối tượng với thao tác**\n\n⚡ Command có thể chuyển hoá một phương thức cụ thể thành một đối tượng độc lập. Thay đổi này mở ra nhiều công dụng hấp dẫn: bạn có thể truyền command như một tham số của phương thức, lưu trữ chúng trong các đối tượng khác, thay đổi command đã liên kết ngay khi đang chạy,...\n\nVí dụ: bạn đang phát triển một thành phần GUI như một menu ngữ cảnh, và bạn muốn người dùng của bản có thể cấu hình các phần của menu để kích hoạt thao tác khi người dùng click vào một mục.\n\n**🐞 Sử dụng Command khi bạn muốn tạo hàng đợi các thao tác, lên lịch các thực thi của chúng hoặc thực thi chúng từ xa**\n\n⚡ Như bất kỳ đối tượng nào khác, command có thể được serialized(chuyển hoá), có nghĩa là chuyển đổi từ một đối tượng thành một chuỗi có thể ghi vào file hay cơ sở dữ liệu. Sau đó, chuỗi có thể được phục hồi lại thành đối tượng command ban đầu. Do đó bạn có thể trì hoãn và lên lịch thực thi command. Với cùng cách đấy bạn có thể xếp hàng(queue), ghi nhật ký(log) hay gửi command qua mạng.\n\n**🐞 Sử dụng Comment khi bạn muốn triển khai các thao tác nghịch đảo**.\n\n⚡ Mặc dù có nhiều cách để thực hiện hoàn tác / làm lại, nhưng Command có lẽ là phổ biến nhất.\n\nĐể có thể hoàn tác các thao tác, bạn cần triển khai lịch sử của các hành động đã thực hiện. Lịch sử command là một ngăn xếp chứa tất cả các đối tượng command đã thực thi cùng với các bản sao lưu liên quan về trạng thái của ứng dụng.\n\nPhương pháp này có hai nhược điểm. Đầu tiên, không dễ dàng để lưu trạng thái của ứng dụng vì một số trong số đó có thể là riêng tư. Vấn đề này có thể được giảm thiểu với pattern **Memento**.\n\nThứ hai, các bản sao lưu trạng thái có thể tiêu tốn khá nhiều RAM. Do đó, đôi khi bạn có thể sử dụng một cách triển khai thay thế: thay vì khôi phục trạng thái trong quá khứ, lệnh thực hiện thao tác nghịch đảo. Hoạt động ngược lại cũng có một cái giá: nó có thể khó hoặc thậm chí không thể thực hiện được.\n\n## 📋 Triển khai\n\n1. Khai báo interface command với phương thức thực thi đơn nhất.\n\n2. Bắt đầu trích xuất yêu cầu vào lớp concrete command, triển khai từ interface command. Mỗi lớp phải có một tập hợp trường cho lưu trữ tham số yêu cầu cùng với tham chiếu đến đối tượng receiver. Tất cả giá trị này được khởi tạo thông qua hàm khởi tạo của command.\n\n3. Xác định các lớp sẽ hành động như sender. Thêm trường lưu trữ command vào các lớp này. Sender sẽ giao tiếp với command của nó chỉ thông qua interface command. Sender thường không tạo đối tượng command cho nó, mà sẽ lấy chúng từ code client.\n\n4. Thay đổi sender để chúng thực thi command thay vì gửi yêu cầu trực tiếp đến receiver.\n\n5. Client nên khởi tạo đối tượng theo trật tự sau:\n    - Tạo receiver.\n    - Tạo command và liên kết với receiver nếu cần.\n    - Tạo sender và liên kết với command cụ thể.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ *Single Responsibility Principle*. Bạn có thể tách các lớp gọi các thao tác từ các lớp thực hiện các thao tác này.\n\n✔️ *Open/Closed Principle*. Bạn có thể thêm command mới vào ứng dụng mà không ảnh hưởng đến code client hiện có.\n\n✔️ Bạn có thể triển khai hoàn tác/làm lại(undo/redo).\n\n✔️ Bạn có thể triển khai thực hiện trì hoãn các thao tác.\n\n✔️ Bạn có thể lắp ghép một tập hợp các command đơn giản thành một tập hợp các command phức tạp\n\n### Nhược điểm\n\n❌ Code có thể trở nên phức tạp hơn vì bạn đang thêm một lớp hoàn toàn mới giữa sender và receiver.\n\n## 🔁 Quan hệ với các pattern khác\n\n**Chain of Responsibility**, **Command**, **Mediator** và **Observer** giải quyết các cách khác nhau để kết nối người gửi và người nhận yêu cầu:\n\n- **CoR** chuyển một yêu cầu tuần tự dọc theo một chuỗi động gồm những người nhận tiềm năng cho đến khi một trong số họ xử lý nó.\n- **Command** thiết lập các kết nối một chiều giữa người gửi và người nhận.\n- **Mediator** loại bỏ các kết nối trực tiếp giữa người gửi và người nhận, buộc họ phải giao tiếp gián tiếp thông qua một đối tượng trung gian.\n- **Observer** cho phép người nhận đăng ký động và hủy đăng ký nhận yêu cầu. \n\nHandler trong **Chain of Responsibility** có thể triển khai như **Command**. Trong trường hợp này bạn có thể thực thi các hành động khác nhau trên cùng một đối tượng ngữ cảnh, được biểu diễn bởi yêu cầu.\n\nBạn có thể sử dụng **Command** và **Memento** cùng nhau khi thực hiện \"hoàn tác\". Trong trường hợp này, các command chịu trách nhiệm thực hiện các hoạt động khác nhau trên một đối tượng đích, trong khi các mementos lưu trạng thái của đối tượng đó ngay trước khi command được thực thi.\n\n**Command** và **Strategy** có thể trông giống nhau vì bạn có thể sử dụng cả hai để tham số hóa một đối tượng bằng một số hành động. Tuy nhiên, chúng có mục đích rất khác nhau.\n\nBạn có thể sử dụng **Command** để chuyển đổi bất kỳ thao tác nào thành một đối tượng. Các tham số của thao tác trở thành các trường của đối tượng đó. Việc chuyển đổi cho phép bạn trì hoãn việc thực hiện thao tác, xếp hàng đợi, lưu trữ lịch sử lệnh, gửi lệnh đến các dịch vụ từ xa, v.v.\n\nMặt khác, **Strategy** thường mô tả các cách khác nhau để thực hiện cùng một việc, cho phép bạn hoán đổi các thuật toán này trong một lớp ngữ cảnh duy nhất.\n\n**Prototype** có thể hữu ích khi bạn cần lưu các bản sao của **Command** vào lịch sử.\n\nBạn có thể coi **Visitor** như một phiên bản mạnh mẽ của **Command**. Các đối tượng của nó có thể thực thi các hoạt động trên các đối tượng khác nhau của các lớp khác nhau.\n\n# Nguồn\n\n[refactoring](https://refactoring.guru/design-patterns/command)"
  },
  {
    "path": "behavioral-pattern/iterator/README.md",
    "content": "# Iterator\n\n## 📜 Mục đích\n\n**Iterator** là một design pattern thuộc nhóm behavioral giúp bạn duyệt phần tử của một tập hợp mà không để lộ dạng cơ bản của nó (danh sách, ngăn xếp, cây, ...)\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nCollection(tập hợp) là một trong những kiểu dữ liệu được sử dụng nhiều nhất trong lập trình. Hiểu đơn giản nó chỉ là nơi chứa cho một nhóm đối tượng.\n\n![problem1](./assets/problem1.png)\n\nPhần lớn tập hợp lưu trữ phần tử của nó bằng các danh sách đơn giản. Tuy nhiên một số lại sử dụng ngăn xếp, cây, đồ thị hoặc một cấu trúc dữ liệu phức tạp nào khác.\n\nNhưng việc tập hợp được tạo như thế nào không quan trọng, nó chỉ cần cung cấp một số cách để các đoạn code khác có thể truy cập và sử dụng phần tử của nó. Thế nên cần có một phương pháp để duyệt qua từng phần tử của tập hợp và đảm bảo truy cập không trùng lặp tại bất kỳ phần tử nào.\n\nĐiều này nghe có vẻ dễ dàng nếu tập hợp của bạn dựa trên dạng danh sách. Bạn chỉ việc lặp lại tất cả phần tử.\n\nNhưng nếu nó là một cấu trúc dữ liệu phức tạp khác như cây thì sao? Ví dụ, hôm nay bạn phải thực hiện duyệt cây theo chiều sâu(depth-first traversal), nhưng ngày hôm sau bạn lại nhận yêu cầu là cần thêm duyệt cây theo chiều rộng(breadth-first traversal), và các ngày kế tiếp bạn phải thực hiện các công việc khác như truy cập ngẫu nhiên ba phần tử,...\n\n![problem2](./assets/problem2.png)\n\n*Một tập hợp có thể duyệt theo nhiều cách*\n\nViệc thêm nhiều thuật toán duyệt vào tập hợp có thể làm mờ đi nhiệm vụ chính của nó, là lưu trữ dữ liệu hiệu quả. Thêm vào đó, một vài thuật toán chỉ phù hợp với vài ứng dụng cơ bản, thế nên thêm nó vào lớp tập hợp chung có thể sẽ không phù hợp.\n\nMặt khác, code client làm việc với nhiều tập hợp khác nhau thường không quan tâm đến chúng lưu trữ phần tử như thế nào. Tuy nhiên, vì tập hợp cung cấp các cách khác nhau để truy cập phần tử, nên bạn không có lựa chọn nào khác ngoài kết hợp code của bạn với lớp tập hợp cụ thể.\n\n## 😊 Giải pháp\n\nÝ tượng ở đây là mở rộng hành vi duyệt của một tập hợp thành một đối tượng riêng biệt gọi là *iterator*.\n\n![solution](./assets/solution1.png)\n\nNgoài việc triển khai thuật toán chính, một đối tượng iterator còn đóng gói tất cả các chi tiết duyệt, chẳng hạn như vị trí hiện tại và số phần tử còn lại của tập hợp. Do đó, nhiều iterator có thể đi qua cùng một một tập hợp cùng lúc, độc lập với nhau.\n\nThông thường, các iterator cung cấp một phương thức chính để tìm nạp các phần tử của tập hợp. Client có thể tiếp tục chạy phương thức này cho đến khi nó không trả về bất kỳ thứ gì, có nghĩa là iterator đã duyệt qua tất cả các phần tử.\n\nTất cả các iterator phải triển khai cùng một interface. Điều này làm cho code client tương thích với bất kỳ loại tập hợp nào hoặc bất kỳ thuật toán duyệt nào miễn là có một iterator thích hợp. Nếu bạn cần một cách đặc biệt để duyệt qua một tập hợp, bạn chỉ cần tạo một lớp iterator mới mà không cần phải thay đổi tập hợp hoặc ứng dụng client.\n\n## 🚗 Thế Giới Thực\n\n![analogy](./assets/analogy.png)\n\nBạn có kế hoạch đi thăm Roma trong vài ngày và tham quan tất cả địa điểm chính nổi bật và thu hút. Nhưng khi đến đó, bạn có thể lãng phí nhiều thời gian để tìm đường, thậm chí bạn còn không thể tìm được đấu trường La Mã(nơi thông với mọi con đường).\n\nMặt khác bạn mua một ứng dụng hướng dẫn cho smartphone của bạn và dùng nó để tìm đường. Nó rất thông minh và tiện lợi, bạn có thể đến bất kỳ nơi thú vị nào mà bạn muốn.\n\nBên cạnh đó bạn cũng có thể bỏ ra một phần tiền cho chuyến đi để mướn một người địa phương, người nắm mọi con đường của thành phố trong lòng bàn tay. Hướng dẫn viên này có thể điều chỉnh hướng đi theo ý thích của bạn, chỉ cho bạn mọi điểm tham quan và kể rất nhiều điển tích thú vị. Điều đó sẽ tuyệt vời hơn ứng dụng điện thoại nhiều; nhưng, than ôi, cũng đắt hơn nhiều. \n\nTất cả các tùy chọn này — đi đường ngẫu nhiên sinh ra trong đầu bạn, hướng dẫn trên điện thoại thông minh hoặc hướng dẫn của con người — hoạt động như các iterator trên tập hợp khổng lồ là các điểm tham quan và danh lam thắng cảnh ở Roma.\n\n## 🏢 Cấu trúc\n\n![structure](./assets/structure.png)\n\n1. **Iterator** là interface khai báo các thao tác bắt buộc cho duyệt một tập hợp: lấy phần tử kế tiếp, trả về vị trí hiện tại, chạy lại vòng lặp,...\n2. **Concrete Iterator** triển khai thuật toán cụ thể cho duyệt tập hợp. Đối tượng iterator nên theo dõi quá trình duyệt của nó. Điều này cho phép nhiều iterator duyệt cùng một tập hợp độc lập với nhau.\n3. **Collection** là interface khai báo một hoặc nhiều phương thức để lấy các iterator tương thích với tập hợp. Lưu ý rằng kiểu trả về của phương thức phải được khai báo như interface iterator để cho concrete collection  có thể trả về kiểu iterator khác.\n4. **Concrete Collections** trả về phiên bản mới của một lớp concrete iterator riêng biệt mỗi khi client yêu cầu nó. Bạn có thể hỏi rằng, phần code còn lại của tập hợp ở đâu ? Không cần lo lắng, nó sẽ ở cùng một lớp. Chỉ là những chi tiết này không thực sự quan trọng đối với pattern, vì vậy ta sẽ bỏ qua chúng.\n5. **Client** làm việc với cả tập hợp và iterator thông qua interface của chúng. Cách này giúp client không phải ghép với lớp cụ thể, cho phép bạn sử dụng các tập hợp và iterator khác trên cùng một code.\nThông thường, client không tạo iterator của nó, thay vào đó nó lấy chúng từ tập hợp. Tuy nhiên, trong một số trường hợp nhất định, client có thể tạo trực tiếp một cái; ví dụ, khi client xác định iterator đặc biệt của riêng nó.\n\n## 👨‍💻 Mã giả\n\nTrong ví dụ này, Iterator được dùng để duyệt qua một tập hợp đặc biệt, một đồ thị mạng xã hội tương tự như Facebook. Tập hợp cung cấp nhiều iterator để duyệt hồ sơ người dùng theo nhiều cách khác nhau.\n\n![pseudocode](./assets/pseudocode.png)\n\nIterator \"friend\" có thể sử dụng để duyệt qua các bạn bè của hồ sơ người dùng được cho. Iterator \"colleagues\" cũng tương tự, ngoại trừ việc nó bỏ qua những người bạn không làm chung công ty với người dùng. Cả hai iterator triển khai cùng interface nên cho phép client lấy thông tin hồ sơ mà không cần đi sâu vào chi tiết triển khai như là xác thực hay gửi yêu cầu REST. .\n\nCode client không phải ghép với lớp cụ thể vì nó làm việc với tập hợp và iterator thông qua interface. Nếu bạn định kết nối ứng dụng của bạn với mạng xã hội mới, bạn chỉ cần làm đơn giản là cung cấp cho nó tập hợp mới và lớp iterator mà không cần thay đổi code hiện có.\n\n```c\n// Interface collection phải khai báo phương thức factory cho\n// tạo các iterator. Bạn có thể khai báo nhiều phương thức nếu\n// nó có các kiểu lặp khác nhau trong chương trình của bạn.\ninterface SocialNetwork is\n    method createFriendsIterator(profileId):ProfileIterator\n    method createCoworkersIterator(profileId):ProfileIterator\n\n\n// Mỗi concrete collection được ghép với tập hợp lớp concrete iterator\n// mà nó trả về. Nhưng client không cần làm vậy, vì signature của phương\n// thức này trả về interface iterator.\nclass Facebook implements SocialNetwork is\n    // ... Phần lớn code của tập hợp sẽ ở đây ...\n\n    // Code tạo iterator.\n    method createFriendsIterator(profileId) is\n        return new FacebookIterator(this, profileId, \"friends\")\n    method createCoworkersIterator(profileId) is\n        return new FacebookIterator(this, profileId, \"coworkers\")\n\n\n// Interface chung cho tất cả iterator.\ninterface ProfileIterator is\n    method getNext():Profile\n    method hasMore():bool\n\n\n// Lớp concrete iterator.\nclass FacebookIterator implements ProfileIterator is\n    // Iterator cần một tham chiếu đến tập hợp mà nó duyệt.\n    private field facebook: Facebook\n    private field profileId, type: string\n\n    // Đối tượng iterator duyệt tập hợp độc lập với các iterator\n    // khác. Do đó nó phải lưu trữ trạng thái iterator.\n    private field currentPosition\n    private field cache: array of Profile\n\n    constructor FacebookIterator(facebook, profileId, type) is\n        this.facebook = facebook\n        this.profileId = profileId\n        this.type = type\n\n    private method lazyInit() is\n        if (cache == null)\n            cache = facebook.socialGraphRequest(profileId, type)\n\n    // Mỗi lớp concrete iterator có triển khai riêng với interface\n    // iterator chung.\n    method getNext() is\n        if (hasMore())\n            currentPosition++\n            return cache[currentPosition]\n\n    method hasMore() is\n        lazyInit()\n        return currentPosition < cache.length\n\n\n// Đây là một mẹo hữu ích khác: bạn có thể truyền một iterator \n// đến lớp client thay vì cấp cho nó quyền truy cập toàn bộ tập\n// hợp. Với cách này bạn sẽ không để lộ tập hợp với client\n//\n// Và một lợi ích khác: bạn có thể thay đổi cách client làm việc\n// với tập hợp khi đang chạy bằng cách truyền vào nó iterator khác.\n// Nó hoàn toàn khả thi vì code client không ghép vói lớp iterator\n// cụ thể.\nclass SocialSpammer is\n    method send(iterator: ProfileIterator, message: string) is\n        while (iterator.hasMore())\n            profile = iterator.getNext()\n            System.sendEmail(profile.getEmail(), message)\n\n\n// Lớp ứng dụng cấu hình tập hợp và iterator, và truyền chúng\n// vào code client.\nclass Application is\n    field network: SocialNetwork\n    field spammer: SocialSpammer\n\n    method config() is\n        if working with Facebook\n            this.network = new Facebook()\n        if working with LinkedIn\n            this.network = new LinkedIn()\n        this.spammer = new SocialSpammer()\n\n    method sendSpamToFriends(profile) is\n        iterator = network.createFriendsIterator(profile.getId())\n        spammer.send(iterator, \"Very important message\")\n\n    method sendSpamToCoworkers(profile) is\n        iterator = network.createCoworkersIterator(profile.getId())\n        spammer.send(iterator, \"Very important message\")\n```\n\n## 💡 Ứng dụng\n\n**🐞 Sử dụng Iterator khi tập hợp của bạn có cấu trúc dữ liệu phức tạp và bạn muốn ẩn sự phức tập đó khỏi client(vì lý do thuận tiện hay bảo mật).**\n\n⚡ Iterator đóng gói các chi tiết công việc với cấu trúc dữ liệu phức tạp, và cung cấp nó cho client bằng những phương thức truy cập đơn giản đến các phần tử. Nó không những đem lại sự thuận lợi cho client, mà còn bảo về tập hợp khỏi các nguy cơ tấn công mà client có thể thực hiện nếu kết nối trực tiếp.\n\n**🐞 Sử dụng Iterator khi muốn giảm code duyệt trùng lặp trên ứng dụng của bạn**\n\n⚡ Code của các thuật toán lặp đặc biệt thường có xu hướng rất cồng kềnh. Khi được đặt trong logic nghiệp vụ của một ứng dụng, nó có thể làm mờ trách nhiệm của code gốc và làm cho nó khó bảo trì hơn. Chuyển code duyệt đến các iterator cụ thể có thể giúp bạn làm cho code của ứng dụng gọn gàng và sạch sẽ hơn.\n\n**🐞 Sử dụng Iterator khi bạn muốn code của bạn có thể duyệt các cấu trúc dữ liệu khác nhau mà kiểu của cấu trúc đấy là không biết trước**.\n\n⚡ Pattern cung cấp một vài interface chung cho cả tập hợp và iterator. Giả sử code của bạn hiện sử dụng các interface này, code sẽ vẫn hoạt động nếu bạn chuyển cho code các loại tập hợp và iterator khác nhau triển khai các interface này.\n\n## 📋 Triển khai\n\n1. Khai báo interface iterator. Ít nhất, nó phải có một phương thức để duyệt phần tử tiếp theo từ một tập hợp. Nhưng để thuận tiện, bạn có thể thêm một số phương pháp khác, chẳng hạn như duyệt phần tử trước đó, theo dõi vị trí hiện tại và kiểm tra kết thúc của lần lặp.\n\n2. Khai báo interface collection và mô tả một phương pháp để nạp các iterator. Kiểu trả về phải trùng với kiểu của interface interator. Bạn có thể khai báo các phương thức tương tự nếu bạn định có một số nhóm iterator khác nhau.\n\n3. Triển khai các lớp concrete iterator cho các tập hợp mà bạn muốn có thể duyệt được bằng iterator. Một đối tượng iterator phải được liên kết với một tập hợp đơn nhất. Thông thường, liên kết này được thiết lập thông qua phương thức khởi tạo của iterator.\n\n4. Triển khai interface collection trong các lớp tập hợp của bạn. Ý tưởng chính là cung cấp cho client một lối tắt để tạo các iterator, được điều chỉnh cho một lớp concrete collection. Đối tượng tập hợp phải chuyển chính nó đến phương thức khởi tạo của iterator để thiết lập liên kết giữa chúng.\n\n5. Xem qua code client để thay thế tất cả code duyệt tập hợp bằng việc sử dụng iterator. Client tìm nạp một đối tượng iterator mới mỗi khi nó cần lặp qua các phần tử của tập hợp.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ *Single Responsibility Principle*. Bạn có thể làm sạch code client và các tập hợp bằng cách trích xuất các thuật toán duyệt cồng kềnh thành các lớp riêng biệt.\n\n✔️ *Open/Closed Principle*. Bạn có thể triển khai các kiểu tập hợp và iterator mới, và truyền nó vào code hiện có mà không gây ra ảnh hưởng gì.\n\n✔️ Bạn có thể lặp song song trên cùng một tập hợp vì mỗi đối tượng iterator chứa trạng thái lặp riêng của nó.\n\n✔️ Vì lý do tương tự, bạn có thể trì hoãn một lần lặp lại và tiếp tục nó khi cần.\n\n### Nhược điểm\n\n❌ Áp dụng pattern có thể là một việc làm quá mức cần thiết nếu ứng dụng của bạn chỉ hoạt động với các tập hợp đơn giản.\n\n❌ Sử dụng iterator thể kém hiệu quả hơn so với việc duyệt trực tiếp các phần tử của một số tập hợp chuyên biệt.\n\n## 🔁 Quan hệ với các pattern khác\n\nBạn có thể sử dụng **Iterator** để duyệt qua các cây **Composite**.\n\nBạn có thể sử dụng **Factory Method** cùng với **Iterator** để cho phép các lớp con của collection trả về các kiểu vòng lặp khác nhau tương thích với các collection.\n\nBạn có thể sử dụng **Memento** cùng với **Iterator** để nắm bắt trạng thái lặp lại hiện tại và khôi phục nó nếu cần.\n\nBạn có thể sử dụng **Visitor** cùng với **Iterator** để xem qua một cấu trúc dữ liệu phức tạp và thực hiện một số thao tác trên các phần tử của nó, ngay cả khi tất cả chúng đều có các lớp khác nhau\n\n# Nguồn\n\n[**refactoring**](https://refactoring.guru/design-patterns/iterator)"
  },
  {
    "path": "behavioral-pattern/mediator/README.md",
    "content": "# Mediator\n\n## 📜 Mục đích\n\nMediator là một desgin pattern thuộc nhóm behavioral giúp bạn giảm các phụ thuộc hỗn tạp giữa các đối tượng. Pattern hạn chế các giao tiếp trực tiếp giữa các đối tượng và buộc nó giao tiếp thông qua đối tượng mediator.\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nGiả sử bạn có một dialog cho tạo và chỉnh sửa thông tin khách hàng. Nó bao gồm các phần tử form khác nhau như text input, checkbox, button, ...\n\n![problem1](./assets/problem1.png)\n\nMột số phần tử trong form có thể tương tác với nhau. Ví dụ, khi chọn \"I have a dog\" ở một chechbox có thể sẽ dẫn đến hiện một input ẩn cho nhập tên chú chó đó. Hay  khi submit một button sẽ phải xác thực các giá trị hợp lệ ở tất cả trường trước khi lưu dữ liệu.\n\n![problem2](./assets/problem2.png)\n\n*Các phần tử có quan hệ với nhau, nên thay đổi một phần tử có thể ảnh hưởng đến những cái khác*\n\nBằng cách triển khai trực tiếp logic bên trong code của phần tử form bạn sẽ làm cho lớp phần tử khó tái sử dụng ở các form khác trong ứng dụng. Ví dụ bạn không thể dùng lớp checkbox này cho các form khác vì nó đã được kết nối với input \"tên chó\". Hoặc là bạn có thể sử dụng tất cả các lớp liên quan đến hiển thị form người dùng hoặc là không dùng được gì cả.\n\n## 😊 Giải pháp\n\nMediator đề nghị giải pháp là bạn nên dừng việc kết nối trực tiếp giữa các thành phần mà bạn muốn nó trở nên độc lập. Thay vào đó, các thành phần này sẽ phải cộng tác gián tiếp qua việc gọi một đối tượng mediator đặc biệt, đối tượng này mới là thứ gọi trực tiếp đến các thành phần thích hợp. Kết quả là các thành phần chỉ phụ thuộc vào lớp mediator duy nhất thay vì được ghép nối với hàng chục  thành phần khác.\n\nTrong ví dụ với form hồ sơ người dùng, lớp diago sẽ hành động như một mediator. Rất có thể, lớp dialog đã nhận thức được các phần tử con của nó, thế nên bạn không cần thêm phụ thuộc mới vào lớp.\n\n![solution1](./assets/solution1.png)\n\nĐây là một thay đổi có ý nghĩa to lớn với các phần tử trong form. Như với button submit. Trước đây mỗi lần người dùng click vào button, nó phải xác thực giá trị hợp lệ của tất cả phần tử riêng biệt trong form. Giờ đây nó chỉ có một công việc là thông báo cho dialog về thao tác click. Khi nhận được thông báo, dialog thực hiện xác thực bản thân nó hoặc truyền công việc cho các phần tử riêng biệt. Do đó thay vì bị ràng buộc với hàng tá phần tử trong form, button chỉ phụ thuộc vào dialog.\n\nBạn có thể làm nhiều hơn là nới lỏng các ràng buộc bằng việc trích xuất interface chung cho tất cả kiểu dialog. Interface sẽ khai báo phương thức thông báo cho tất cả phần tử của form để thông báo đến dialog mỗi khi có sự kiện gì diễn ra với bọn chúng. Do đó, button submit của ta bây giờ có thể làm việc với bất kỳ dialog nào triển khai interface này.\n\nBằng cách này, Mediator giúp bạn gói một trang web phức tạp với các đối tượng có quan hệ khác nhau vào trong một đối tượng mediator đơn giản. Ít ràng buộc và phụ thuộc hơn, giúp nó dễ thay đổi, mở rộng và tái sử dụng hơn.\n\n## 🚗 Thế Giới Thực\n\n![analogy](./assets/analogy.png)\n\nCác phi công của máy bay đến hoặc rời đi khỏi khu vực kiểm soát của sân bay không phải liên lạc trực tiếp với nhau. Thay vào đó, họ trao đổi với một nhân viên kiểm soát không lưu, người ngồi trong một tòa tháp cao ở đâu đó gần đường băng. Nếu không có kiểm soát viên không lưu, các phi công sẽ cần phải biết về mọi máy bay trong khu vực lân cận sân bay, thảo luận về các ưu tiên hạ cánh với một nhóm gồm hàng chục phi công khác. Điều đó có thể sẽ làm tăng vọt số liệu thống kê về các vụ tai nạn máy bay.\n\nTháp không cần điều khiển toàn bộ chuyến bay. Nó chỉ tồn tại để thực thi các ràng buộc trong khu vực hạ cánh vì số lượng các máy bay ở đó có thể quá tải đối với một phi công.\n\n## 🏢 Cấu trúc\n\n![structure](./assets/structure.png)\n\n1. **Component** là các lớp khác nhau bao gồm các logic nghiệp vụ. Mỗi component có một tham chiếu đến một mediator, khai báo kiểu của interface mediator. Component không cần biết về lớp thực sự của mediator, nên bạn có thể sử dụng lại component cho các chương trình khác bằng cách liên kết nó với một mediator khác.\n2. **Mediator** là interface khai báo phương thức giao tiếp giữa các component, nó thường khai báo một phương thức thông báo duy nhất. Component có thể truyền bất kỳ ngữ cảnh nào như các tham số của phương thức này bao gồm cả đối tượng của chúng, nhưng chỉ trong trường hợp không diễn ra kết ghép giữa component nhận và lớp của người gửi.\n3. **Concrete Mediator** đóng gói quan hệ giữa các component khác nhau. Concrete mediator thường giữ tham chiếu để tất cả component nó quản lý và thỉnh thoảng quản lý cả vòng đời của chúng.\n4. Component không phải biết về các component khác. Nếu một điều gì quan trọng diễn ra với một component, nó chỉ việc thông báo đến mediator. Khi mediator nhận thông báo nó có thể xác định được người gửi dễ dàng, chỉ như vậy là đủ để nó quyết định component nào sẽ được kích hoạt khi trả về.\n\n    Từ góc nhìn của một component, tất cả trông giống như một hộp đen. Người gửi không biết ai sẽ xử lý yêu cầu của mình và người nhận không biết ai đã gửi yêu cầu ngay từ đầu.\n\n\n## 👨‍💻 Mã giả\n\nTrong ví dụ này, Mediator  giúp bạn loại bỏ sự phụ thuộc lẫn nhau giữa các lớp UI khác nhau: button, checkbox và text labels.\n\n![pseudocode](./assets/pseudocode.png)\n\nMột phần tử được kích hoạt bởi người dùng, không cần giao tiếp trực tiếp với các phần tử khác. Thay vào đó, các phần tử chỉ cần cho mediator của chúng biết khi có sự kiện diễn ra, truyền thông tin ngữ cảnh cùng với thông báo.\n\nTrong ví dụ này, các dialog hành động như một mediator. Nó biết làm thế nào để các phần tử cụ thể cộng tác với nhau và tạo điều kiện cho chúng kết nối gián tiếp với nhau. Mỗi khi nhận thông báo về một sự kiện, dialog quyết định phần tử nào sẽ giải quyết và chuyền hướng lệnh gọi phù hợp.\n\n```c\n// Interface mediator khai báo một phương thức được dùng bởi\n// các component để thông báo cho mediator về các sự kiện khác\n// nhau. Mediator sẽ phản ứng với sự kiện và truyền thực thi\n// cho các component khác.\ninterface Mediator is\n    method notify(sender: Component, event: string)\n\n\n// Lớp concrete mediator. Các kết nối phức tạp giữa các\n// component riêng biệt đã được gỡ rối và chuyền vào mediator.\nclass AuthenticationDialog implements Mediator is\n    private field title: string\n    private field loginOrRegisterChkBx: Checkbox\n    private field loginUsername, loginPassword: Textbox\n    private field registrationUsername, registrationPassword,\n                  registrationEmail: Textbox\n    private field okBtn, cancelBtn: Button\n\n    constructor AuthenticationDialog() is\n        // Tạo tất cả đối tượng component và truyền mediator\n        // hiện tại vào hàm khởi tạo để thiết lập liên kết.\n\n\n    // Khi điều gì đó diễn ra với một component, nó thông báo cho\n    // mediator. Khi nhận được thông báo, mediator sẽ làm gì đó \n    // hoặc truyền yêu cầu đến component khác.\n    method notify(sender, event) is\n        if (sender == loginOrRegisterChkBx and event == \"check\")\n            if (loginOrRegisterChkBx.checked)\n                title = \"Log in\"\n                // 1. Hiện form đăng nhập \n                // 2. Ẩn form đăng ký.\n            else\n                title = \"Register\"\n                // 1. Hiện form đăng ký \n                // 2. Ẩn form đăng nhập.\n\n        if (sender == okBtn && event == \"click\")\n            if (loginOrRegister.checked)\n                // Tìm kiếm người dùng bằng chứng chỉ đăng nhập.\n                if (!found)\n                    // Hiện thông báo lỗi trên trường đăng nhập.\n            else\n                // 1. Tạo tài khoản người dùng sử dụng dữ liệu\n                // từ trường đăng ký.\n                // 2. Đăng nhập người dùng.\n                // ...\n                \n\n// Component giao tiếp với mediator thông qua interface mediator.\n// Nhờ điều đó, bạn có thể dùng cùng một component trong các\n// bối cảnh khác nhau bằng liên kết với các đối tượng mediator\n// khác nhau.\nclass Component is\n    field dialog: Mediator\n\n    constructor Component(dialog) is\n        this.dialog = dialog\n\n    method click() is\n        dialog.notify(this, \"click\")\n\n    method keypress() is\n        dialog.notify(this, \"keypress\")\n\n// Mỗi concrete component không giao tiếp với nhau. Chúng chỉ\n// có một kênh giao tiếp để gửi thông báo đến mediator.\nclass Button extends Component is\n    // ...\n\nclass Textbox extends Component is\n    // ...\n\nclass Checkbox extends Component is\n    method check() is\n        dialog.notify(this, \"check\")\n    // ...\n```\n\n## 💡 Ứng dụng\n\n**🐞 Sử dụng Mediator khi việc thay đổi một vài lớp trở nên khó khăn do chúng được kết ghép chặt chẽ với các lớp khác**\n\n⚡ Pattern giúp bạn trích xuất các quan hệ giữa các lớp vào một lớp riêng biệt, cô lập bất kỳ thay đổi nào đến một thành phần cụ thể khỏi các thành phần còn lại.\n\n**🐞 Sử dụng Mediator khi bạn không thể dùng lại một thành phần ở chương trình khác vì nó phụ thuộc vào các thành phần khác**.\n\n⚡ Sau khi áp dụng Mediator, các thành phần cụ thể sẽ không biết đến các thành phần khác. Chúng chỉ giao tiếp với nhau một cách gián tiếp thông qua đối tượng mediator. Để dùng lại một thành phần ở ứng dụng khác, bạn cần cung cấp cho nó một lớp mediator mới.\n\n**🐞 Sử dụng Mediator khi bạn phải tạo hàng tấn thành phần con chỉ để sử dụng lại vài hành vi cơ bản cho các bối cảnh khác nhau**.\n\n⚡ Vì tất cả các mối quan hệ giữa các thành phần được chứa trong mediator, nên thật dễ dàng xác định các cách hoàn toàn mới cho các thành phần này cộng tác bằng cách thêm các lớp mediator mới mà không cần phải thay đổi chính các thành phần đó.\n\n## 📋 Triển khai\n\n1. Xác định xem một nhóm các lớp kết nối chặt chẽ có tốt hơn việc chúng độc lập với nhau không(có dễ bảo trì hay dùng lại các lớp này không).\n\n2. Khai báo interface mediator và mô tả giao thức giao tiếp mong muốn giữa mediator và các thành phần khác. Trong hầu hết trường hợp, một phương thức duy nhất cho nhận các thông báo từ các thành phần là đủ.\n\n    Interface này là cốt yếu khi bạn muốn sử dụng lại lớp thành phần ở ngữ cảnh khác. Miễn là thành phần làm việc với mediator thông qua interface chung, bạn có thể liên kết thành phần với triển khai khác của mediator.\n\n3. Triển khai lớp mediator cụ thể. Lớp này dùng để lưu trữ tham chiếu đến tất cả thành phần mà nó quản lý.\n\n4. Bạn có thể để mediator chịu trách nhiệm tạo và huỷ các đối tượng thành phần. Lúc này, mediator sẽ giống như một factory hay facade.\n\n5. Các thành phần nên lưu một tham chiếu đến đối tượng mediator. Kết nối này thường được thiết lập ở hàm khởi tạo thành phần, nơi một đối tượng mediator được truyền như một tham số.\n\n6. Thay đổi code của component này sẽ gọi đến phương thức thông báo của mediator thay vì đến phương thức của các thành phần khác. Trích xuất code để gọi đến thành phần khác vào lớp mediator. Thực thi code này bất cứ khi nào mediator nhận được thông báo.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ *Single Responsibility Principle*. Bạn có thể trích xuất giao tiếp giữa các thành phần khác vào một nơi duy nhất, giúp nó dễ hiểu và bảo trì hơn.\n\n✔️ *Open/Closed Principle*. Bạn có thể thêm mediator mới mà không ảnh hưởng gì đến các thành phần thực sự.\n\n✔️ Bạn có thể làm giảm liên kết giữa các thành phần khác nhau trong chương trình.\n\n✔️ Bạn có thể sử dụng lại các thành phần cụ thể một cách dễ dàng.\n\n### Nhược điểm\n\n❌ Theo thời gian mediator có thể phát triển thành một [Đối tượng thượng đế](https://vi.wikipedia.org/wiki/Đối_tượng_thượng_đế_(Lập_trình_máy_tính))\n\n## 🔁 Quan hệ với các pattern khác\n\n**Chain of Responsibility**, **Command**, **Mediator** và **Observer** giải quyết các cách khác nhau để kết nối người gửi và người nhận yêu cầu:\n\n- **CoR** chuyển một yêu cầu tuần tự dọc theo một chuỗi động gồm những người nhận tiềm năng cho đến khi một trong số họ xử lý nó.\n- **Command** thiết lập các kết nối một chiều giữa người gửi và người nhận.\n- **Mediator** loại bỏ các kết nối trực tiếp giữa người gửi và người nhận, buộc họ phải giao tiếp gián tiếp thông qua một đối tượng trung gian.\n- **Observer** cho phép người nhận đăng ký động và hủy đăng ký nhận yêu cầu. \n\n**Facade** và **Mediator** có những công việc tương tự nhau: cố gắng tổ chức sự hợp tác giữa nhiều lớp được kết hợp chặt chẽ với nhau.\n\n- **Facade** xác định một interface đơn giản cho một hệ thống con của các đối tượng, nhưng nó không giới thiệu bất kỳ chức năng mới nào. Bản thân hệ thống con không biết về facade. Các đối tượng trong hệ thống con có thể giao tiếp trực tiếp.\n- **Mediator** tập trung giao tiếp giữa các thành phần của hệ thống. Các thành phần chỉ biết về đối tượng mediator và không giao tiếp trực tiếp.\n\nSự khác biệt giữa **Mediator** và **Observer** thường khó nắm bắt. Trong hầu hết các trường hợp, bạn có thể triển khai một trong các mẫu này; nhưng đôi khi bạn có thể áp dụng đồng thời cả hai. Hãy xem chúng ta có thể làm điều đó như thế nào.\n\n- Mục tiêu chính của **Mediator** là loại bỏ sự phụ thuộc lẫn nhau giữa một tập hợp các thành phần hệ thống. Thay vào đó, các thành phần này trở nên phụ thuộc vào một đối tượng mediator duy nhất. Mục tiêu của **Observer** là thiết lập các kết nối động một chiều giữa các đối tượng, nơi một số đối tượng đóng vai trò là cấp dưới của những đối tượng khác.\n\n- Có một cách triển khai phổ biến của **Mediator** vào **Observer**. Đối tượng mediator đóng vai trò là publisher và các thành phần đóng vai trò là subscribers, đăng ký và hủy đăng ký tham gia các sự kiện của mediator. Khi **Mediator** được triển khai theo cách này, nó có thể trông rất giống với **Observer**.\n\n- Nếu thấy bối rối, hãy nhớ rằng bạn có thể triển khai **Mediator** theo những cách khác. Ví dụ: bạn có thể liên kết vĩnh viễn tất cả các thành phần với cùng một đối tượng mediator. Việc triển khai này sẽ không giống với **Observer** nhưng vẫn sẽ là một bản sao của **Mediator**.\n\n- Bây giờ hãy tưởng tượng một chương trình mà tất cả các thành phần đã trở thành publisher, cho phép các kết nối động với nhau. Sẽ không có đối tượng mediator tập trung, chỉ có một nhóm observer phân tán.\n\n# Nguồn\n\n[**refactoring**](https://refactoring.guru/design-patterns/mediator)"
  },
  {
    "path": "behavioral-pattern/memento/README.md",
    "content": "# Memento\n\n## 📜 Mục đích\n\nMemento là một desgin pattern thuộc nhóm behavioral giúp bạn lưu và phục hồi trạng thái trước đó của một đối tượng mà không để lộ chi tiết triển khai của nó\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nTưởng tượng bạn đang tạo một ứng dụng soạn thảo văn bản. Bên cạnh việc chỉnh sửa đơn giản, bạn còn phải tạo chức năng định dạng văn bản, thêm ảnh, chỉnh phông,...\n\nVào một lúc nào đó, bạn quyết định thêm chức năng giúp người dùng hoàn tác bất kỳ thao tác nào được thực hiện trên văn bản. Chức năng này rất phổ biến trong thời gian gần đây và người dùng sẽ mong muốn là mọi ứng dụng đều có nó.\nĐể triển khai, bạn chọn cách tiếp cận trực tiếp. Là trước khi thực hiện bất kỳ thao tác nào, ứng dụng sẽ ghi lại trạng thái của tất cả đối tượng trong nó và lưu chúng vào một vài nơi lưu trữ. Sau đó, khi người dùng muốn hoàn tác hành động, ứng dụng  sẽ lấy snapshot (bản lưu nhanh) gần nhất trong lịch sử và dùng nó để phục hồi trạng thái của mọi đối tượng.\n\n![problem1](./assets/problem1.png)\n\nBây giờ ta xem xét kỹ snapshot của các trạng thái này. Câu hỏi đặt ra là làm thế nào để bạn tạo chính xác chúng? Có lẽ bạn sẽ đi qua tất cả trường trong đối tượng và sao chép giá trị của chúng rồi lưu vào bộ nhớ. Tuy nhiên nó sẽ chỉ hoạt động nếu đối tượng của bạn không hạn chế truy cập đến nội dung của nó. Không may, phần lớn đối tượng thực sẽ không để những thứ bên ngoài truy cập vào bên trong của nó dễ dàng, nó sẽ ẩn tất cả dữ liệu có ích vào các trường riêng tư.\n\nTạm thời ta bỏ qua vấn đề này và mặc định rằng tất cả đối tượng của chúng ta đều như những con hà mã: thích các quan hệ mở và công khai trạng thái của chúng. Lúc này, ngay cả khi cách tiếp cận trên giải quyết được vấn đề và giúp bạn tạo snapshot của trạng thái đối tượng tuỳ ý, thì nó vẫn tồn đọng nhiều vấn đề nghiêm trọng khác. Trong tương lai, khi bạn quyết định tái cấu trúc  một vài lớp chỉnh sửa, tức là thêm hoặc xoá một vài trường. Điều này sẽ không dễ dàng vì bạn phải thay đổi tất cả các lớp chịu trách nhiệm cho sao chép trạng thái của đối tượng bị ảnh hưởng.\n\n![problem2](./assets/problem2.png)\n\nHơn thế nữa. Hãy xem xét các snapshot trạng thái của trình soạn thảo. Dữ liệu trong nó bao gồm những gì? Ở mức tối thiểu, nó phải bao gồm các văn bản thực, toạ độ con trỏ, vị trí hiện tại đang scroll,... Để tạo snapshot, bạn cần phải tìm kiếm các giá trị này và đặt chúng vào trong một dạng container.\n\nCó thể, bạn sẽ lưu một lượng đối tượng container này trong một vài danh sách để biểu diễn lịch sử thao tác. Do đó, container có lẽ là sẽ trở thành đối tượng của một lớp. Lớp này không có phương thức, những có nhiều trường để ánh xạ trạng thái của trình soạn thảo. Để cho phép các đối tượng khác viết và đọc dữ liệu từ snapshot, bạn phải công khai tất cả các trường của nó. Điều này vô tình làm lộ trạng thái của ứng dụng bất kể nó riêng tư hay không. Các lớp khác sẽ trở nên phụ thuộc vào mọi thay đổi dù rất nhỏ ở lớp snapshot, ngược lại nếu các trường và phương thức này riêng tư thì những gì diễn ra trong đây sẽ không ảnh hưởng gì đến bên ngoài lớp.\n\nCó vẻ như chúng ta đã đi đến ngõ cụt: bạn để lộ tất cả các chi tiết bên trong của các lớp, khiến chúng quá mỏng manh(dễ bị thay đổi), còn nếu hạn chế quyền truy cập vào trạng thái của chúng, thì bạn không thể tạo snapshot. Có cách nào khác để thực hiện \"hoàn tác\" không?\n\n## 😊 Giải pháp\n\nTất cả vấn đề trên mà ta gặp phải đều được gây ra bởi hành vi phá vỡ tính đóng gói. Một vài đối tượng cố làm nhiều hơn những gì chúng phải làm. Để thu thập dữ liệu cần thiết cho thực hiện một vài hành động, chúng xâm lấn sang các không gian riêng tư của các đối tượng khác thay vì để các đối tượng đó thực hiện hành động thực.\n\nMemento đề xuất giải pháp uỷ thác việc tạo các snapshot trạng thái cho các chủ sở hữu thực của trạng thái đó, tức là đối tượng gốc. Do đó, thay vì để đối tượng khác cố sao chép trạng thái của trình soạn thảo từ bên ngoài, lớp trình soạn thảo sẽ tự tạo snapshot của chúng vì nó có đầy đủ quyền truy cập vào trạng thái của chúng.\n\nÝ tưởng lưu trữ bản sao của trạng thái đối tượng vào một đối tượng đặc biệt gọi là memento. Nội dung của memento không thể bị truy cập bởi bất kỳ đối tượng nào khác ngoại trừ cái đã tạo ra nó. Các đối tượng khác phải giao tiếp với memento bằng một interface giới hạn, cho phép nạp metadata của snapshot(thời gian tạo, tên thao tác, ...) nhưng không được đụng đến trạng thái của đối tượng ban đầu có trong snapshot.\n\n![solution](./assets/solution.png)\n\n*Originator có đầy đủ quyền truy cập đến memento, trong khi caretaker chỉ có thể thể truy cập đến siêu dữ liệu.*\n\nMột chính sách hạn chế như vậy giúp bạn lưu memento bên trong các đối tượng khác, thường được gọi là caretaker. Vì caretaker làm việc với memento thông qua interface giới hạn, nó không thể can thiệp vào trạng thái được lưu trong memento. Trong khi đó, originator có thể truy cập đến tất cả trường trong memento, cho phép nó khôi phục trạng thái trước đó theo ý muốn.  \n\nTrong ví dụ trình soạn thảo của chúng ta, ta có thể tạo một lớp lịch sử riêng biệt như một caretaker. Ngăn xếp các memento được lưu bên trong caretaker sẽ phát triển mỗi khi trình soạn thảo thực thi một thao tác. Bạn có thể render ngăn xếp vào UI của ứng dụng, như hiển thị lịch sử các thao tác trước đó của người dùng.\n\nKhi người dùng thực hiện hoàn tác, lịch sử sẽ lấy memento gần nhất khỏi ngăn xếp và truyền nó trở lại vào trình soạn thảo, yêu cầu phục hồi. Vì trình soạn thảo có đầy đủ truy cập đến memento, nó sẽ thay đổi trạng thái của nó với giá trị nhận được từ memento.\n\n## 🏢 Cấu trúc\n\n### Triển khai dạng lớp lồng nhau\n\nCách triển khai cổ điển dựa trên các lớp lồng nhau, khả dụng với các ngôn ngữ lập trình phổ biến như C++, C#, Java.\n\n![structure](./assets/structure1.png)\n\n1. **Originator** lớp tạo các snapshot cho trạng thái của nó, cũng như phục hồi trạng thái của nó từ snapshot khi cần.\n2. **Memento** là đối tượng giá trị hành động như một snapshot của trạng thái của originator. Thường thì memento sẽ bất biến và truyền dữ liệu cho nó chỉ một lần thông qua hàm khởi tạo.\n3. **Caretaker** không chỉ biết \"khi nào\" và \"tại sao\" phải lưu trạng thái của originator, mà còn biết trạng thái sẽ được phục hồi khi nào.\n    \n    Một caretaker có thể theo dõi lịch sử của originator bằng cách lưu trữ một ngăn xếp memento. Khi originator đi ngược về lịch sử, caretaker tìm nạp memento trên cùng từ ngăn xếp và truyền nó vào phương thức phục hồi của originator.\n\n4. Trong triển khai này, lớp memento được lồng trong originator. Cách này giúp originator truy cập đến tất cả trường và phương thức của memento, kể cả khi chúng là riêng tư. Mặt khác, caretaker bị giới hạn truy cập đến trường và phương thức của memento, nó chỉ lưu trữ memento trong một ngăn xếp chứ không thể can thiếp vào trạng thái của chúng.\n\n### Triển khai dựa trên interface trung gian\n\nCó một cách triển khai thay thế, phù hợp với các ngôn ngữ lập trình không hỗ trợ các lớp lồng nhau (vâng, tôi đang nói về PHP).\n\n![structure](./assets/structure2.png)\n\n1. Nếu không dùng lớp lồng nhau, bạn có thể hạn chế truy cập đến trường của memento bằng cách thiết lập một quy ước rằng caretaker có thể làm việc với memento chỉ qua một interface trung gian khai báo rõ ràng, nó chỉ khai báo phương thức cho liên kết đến siêu dữ liệu của memento.\n2. Mặt khác, originator có thể làm việc với một đối tượng memento trực tiếp, truy cập trường và phương thức được khai báo trong lớp memento. Nhược điểm của các tiếp cận này là bạn cần khai báo tất cả thành phần của memento công khai.\n\n### Triển khai với tính đóng gói chặt chẽ hơn\n\nCó một cách triển khai khác rất hữu ích khi bạn không muốn để lại mọt rủi ro nhỏ nhất nào cho các lớp khác truy cập vào trạng thái của trình khởi tạo thông qua memento.\n\n![structure](./assets/structure3.png)\n\n1. Triển khai này cho phép nhiều kiểu của originator và memento. Mỗi originator làm việc với lớp memento phù hợp. Không có originator cũng như memento nào để lộ trạng thái của nó với bên ngoài.\n2. Caretaker bây giờ bị giới hạn rõ ràng trong việc thay đổi trạng thái được lưu trong memento. Hơn thế nữa, lớp caretaker sẽ độc lập với originator vì phương thức phục hồi giờ được định nghĩa trong lớp memento.\n3. Mỗi memento trở thành một liên kết với originator đã tạo nó. Originator truyền vào nó hàm khởi tạo của memento, cùng với giá trị trạng thái của nó. Vì quan hệ chặt chẽ giữa các lớp, nên một memento có thể phục hồi trạng thái của originator,  với điều kiện là phần sau đã xác định các bộ thiết lập thích hợp. \n\n## 👨‍💻 Mã giả\n\nVí dụ này sử dụng Memento cùng với Commend để lưu trữ snapshot về trạng thái của trình soạn thảo văn bản phức tạp và khôi phục trạng thái trước đó từ các snapshot này khi cần.\n\n![pseudocode](./assets/pseudocode.png)\n\nĐối tượng command hành động như một caretaker. Chúng tìm nạp memento của trình soạn thảo trước khi thực thi thao tác liên quan đến command. Khi người dùng thực hiện hoàn tác câu lệnh gần nhất, trình soạn thảo có thể sử dụng memento được lưu trong command để hoàn tác trạng thái trước đó của nó.\n\nLớp memento không khai báo bất kỳ trường công khai nào dù là getter hay setter. Do đó không có đối tượng nào có thể thay đổi nội dung của nó. Memento được liên kết với đối tượng soạn thảo đã tạo nó. Điều này giúp một memento phục hồi trạng thái của trình soạn thảo được liên kết bằng cách truyền dữ liệu thông qua setter trên đối tượng soạn thảo. Vì memento được liên kết với đối tượng soạn thảo cụ thể, bạn có thể làm cho ứng dụng hỗ trợ nhiều trình soạn thảo độc lập với ngăn xếp hoàn tác trung tâm.\n\n```c\n// Originator tổ chức một vài dữ liệu quan trọng có thể thay đổi \n// nhiều lần. Nó còn định nghĩa một phương thức cho lưu trữ và \n// phục hồi trạng thái của nó.\nclass Editor is\n    private field text, curX, curY, selectionWidth\n\n    method setText(text) is\n        this.text = text\n\n    method setCursor(x, y) is\n        this.curX = x\n        this.curY = y\n\n    method setSelectionWidth(width) is\n        this.selectionWidth = width\n\n    // Lưu trạng thái hiện tại vào trong memento.\n    method createSnapshot():Snapshot is\n        // Memento là một đối tượng bất biến; điều này\n        // giải thích tại sao originator truyền trạng\n        // thái của nó như tham số vào hàm khởi tạo\n        // của memento.\n        return new Snapshot(this, text, curX, curY, selectionWidth)\n\n// Lớp memento lưu trữ trạng thái trước đó của trình soạn thảo.\nclass Snapshot is\n    private field editor: Editor\n    private field text, curX, curY, selectionWidth\n\n    constructor Snapshot(editor, text, curX, curY, selectionWidth) is\n        this.editor = editor\n        this.text = text\n        this.curX = x\n        this.curY = y\n        this.selectionWidth = selectionWidth\n\n    // Cùng thời điểm, trạng thái trước đó của trình soạn thảo\n    // có thể phục hồi bằng cách sử dụng đối tượng memento.\n    method restore() is\n        editor.setText(text)\n        editor.setCursor(curX, curY)\n        editor.setSelectionWidth(selectionWidth)\n\n// Đối tượng command hành động như một caretaker. Trong trường\n// hợp này, command lấy memento trước khi trạng thái của originator\n// thay đổi. Khi hoàn tác, nó phục hồi trạng thái của originator\n// từ memento.\nclass Command is\n    private field backup: Snapshot\n\n    method makeBackup() is\n        backup = editor.createSnapshot()\n\n    method undo() is\n        if (backup != null)\n            backup.restore()\n    // ...\n```\n\n## 💡 Ứng dụng\n\n**🐞 Sử dụng Memento khi bạn muốn tạo snapshot của trạng thái đối tương để phục hồi trạng trước đó của đối tượng**\n\n⚡ Memento giúp bạn tạo bản sao chép đầy đủ trạng thái của một đối tượng, kể cả trường riêng tư, và lưu chúng riêng biệt với đối tượng. Trong khi phần lớn mọi người sử dụng pattern này cho hoàn tác thì nó cũng được dùng cho xử lý giao dịch(nếu bạn cần khôi phục thao tác lỗi).\n\n**🐞 Sử dụng Memento khi truy cập trực tiếp tới trường/getter/setter của đối tượng vi phạm tính đóng gói**\n\n⚡ Memento giúp đối tượng tự chịu trách nhiệm tạo snapshot trạng thái của nó. Không đối tượng nào khác có thể đọc snapshot, giúp dữ liệu trạng thái của đối tượng ban đầu trở nên an toàn và bảo mật.\n\n## 📋 Triển khai\n\n1. Xác định lớp nào đóng vai trò originator. Điều này là cần thiết để biết chương trình sử dụng một đối tượng trung tâm hay nhiều đối tượng nhỏ hơn.\n2. Tạo lớp memento. Từng cái một, khai báo tập hợp trường ánh xạ các trường được khai báo ở lớp originator.\n3. Làm memento bất biến. Memento chỉ nhận dữ liệu một lần thông qua hàm khởi tạo. Lớp này không có setter.\n4. Nếu ngôn ngữ lập trình hỗ trợ lồng lớp, lồng memento vào originator. Nếu không, trích xuất interface trống từ lớp memento và làm tất cả đối tượng khác sử dụng nó tham chiếu đến memento. Bạn có thể thêm thao tác metadata đến interface nhưng không để lộ thứ gì của trạng thái originator.\n\n5. Thêm một phương thức cho tạo memento ở lớp originator. Originator chỉ truyền trạng thái của nó đến memento thông qua một hoặc nhiều tham số của hàm khởi tạo memento.\n    \n    Kiểu trả về của phương thức nên là interface bạn trích xuất ở bước trước đó (giả sử bạn trích xuất nó ở mọi nơi). Bên trong nó, phương thức tạo memento nên làm việc trực tiếp với lớp memento.\n\n6. Thêm một phương thức cho phục hồi trạng thái của lớp originator. Nó chấp nhận một đối tượng memento như một tham số. Nếu bạn trích xuất một interface ở bước trước, làm nó có kiểu của tham số. Trong trường hợp này, bạn cần ép kiểu đối tượng vào lớp memento, vì originator cần đầy đủ truy cập đến đối tượng này.\n\n7. Caretaker, cho dù nó biểu diễn một đối tượng command, một lịch sử hoặc một cái gì đó hoàn toàn khác, thì cũng cần biết khi nào yêu cầu memento mới từ originator, cách lưu trữ chúng và khi nào thì khôi phục originator bằng một memento cụ thể.\n\n8. Mối liên hệ giữa caretaker và originator có thể được chuyển vào lớp memento. Trong trường hợp này, mỗi memento phải được kết nối với originator đã tạo ra nó. Phương thức khôi phục cũng sẽ chuyển sang lớp memento. Tuy nhiên, tất cả điều này sẽ chỉ có ý nghĩa nếu lớp memento được lồng vào originator hoặc lớp originator cung cấp đủ setter để ghi đè trạng thái của nó.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ Bạn có thể tạo snapshot cho trạng thái đối tượng mà không vi phạm tính đóng gói.\n\n✔️ Bạn có thể đơn giản hoá của của originator bằng cách cho phép caretaker duy trì lịch sử trạng thái của originator.\n### Nhược điểm\n\n❌ Ứng dụng có thể tốn nhiều RAM nếu client thường xuyên tạo memento.\n\n❌ Caretaker nên theo dõi vòng đời của originator để có thể huỷ memento hết hạn.\n\n❌ Nhiều ngôn ngữ lập trình động như PHP, Python và JavaScript không bảo đảm trạng thái trong memento sẽ an toàn.\n\n## 🔁 Quan hệ với các pattern khác\n\nBạn có thể sử dụng **Memento** cùng với **Iterator** để nắm bắt trạng thái lặp lại hiện tại và khôi phục nó nếu cần.\n\nBạn có thể sử dụng **Command** và **Memento** cùng nhau khi thực hiện \"hoàn tác\". Trong trường hợp này, các command chịu trách nhiệm thực hiện các hoạt động khác nhau trên một đối tượng đích, trong khi các mementos lưu trạng thái của đối tượng đó ngay trước khi command được thực thi.\n\nĐôi khi **Prototype** có thể là một giải pháp thay thế đơn giản hơn cho **Memento**. Điều này hoạt động nếu đối tượng, trạng thái mà bạn muốn lưu trữ trong lịch sử, khá đơn giản và không có liên kết đến tài nguyên bên ngoài hoặc các liên kết dễ thiết lập lại.\n\n# Nguồn\n\n[**refactoring**](https://refactoring.guru/design-patterns/memento)"
  },
  {
    "path": "behavioral-pattern/observer/README.md",
    "content": "# Observer\n\n## 📜 Mục đích\n\nObserver là một design pattern thuộc nhóm behavioral giúp bạn định nghĩa một cơ chế đăng ký để thông báo cho nhiều đối tượng về bất kỳ sự kiện nào diễn ra với đối tượng mà chúng đang quan sát.\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nTưởng tượng bạn có hai kiểu đối tượng: `Customer` và `Store`.\n\nKhách hàng thường sẽ bị hấp dẫn với một vài thương hiệu sản phẩm nổi bật, ví dụ như mẫu iPhone mới sẽ sớm được bán ở của hàng. Thế nên họ sẽ đến cửa hàng mỗi ngày để kiểm tra sản phẩm đã có bán chưa. Nhưng nếu sản phẩm vẫn chưa nhập về, thì phần lớn công sức của họ cho mỗi chuyến đi sẽ vô nghĩa.\n\n![problem](./assets/problem.png)\n\nThế nên, cửa hàng sẽ gửi hàng tấn mail (có thể là spam) cho tất cả khách hàng mỗi lần có sản phẩm mới. Điều này giúp khách hàng tránh những chuyến đi vô nghĩa đến cửa hàng. Nhưng bù lại, nó sẽ làm cho các khách hàng khác (những người không có hứng thú với sản phẩm mới) khó chịu.\n\nCó vẻ như chúng ta đã xảy ra xung đột. Hoặc khách hàng lãng phí thời gian kiểm tra sản phẩm đã bán chưa hoặc cửa hàng lãng phí nguồn lực để thông báo thừa cho khách hàng.\n\n## 😊 Giải pháp\n\nĐối tượng có trạng thái hấp dẫn thường được gọi là subject(chủ thể), nhưng vì nó cũng sẽ thông báo cho các đối tượng khác về những thay đổi đối với trạng thái của nó, nên ta sẽ gọi nó là **publisher**. Tất cả đối tượng khác muốn theo dõi trạng thái của publisher được gọi là **subscriber**.\n\nPattern Observer đề nghị giải pháp là bạn thêm một cơ chế đăng ký đến lớp publisher để các đối tượng riêng biệt có thể đăng ký hoặc huỷ đăng ký một dòng các sự kiện xảy đến từ publisher. Thực tế, cơ chế này bao gồm một trường mảng cho lưu trữ danh sách tham chiếu đến đối tượng subscriber và nhiều phương thức công khai cho phép thêm hay xoá subscriber khỏi danh sách.\n\n![solution1](./assets/solution1.png)\n\nBây giờ, bất cứ khi nào có sự kiện quan trọng diễn ra với publisher, nó đi qua tất cả subscriber và gọi phương thức thông báo cụ thể trên đối tượng của chúng.\n\nỨng dụng thực có thể có hàng tá lớp subscriber khác nhau quan tâm đến việc theo dõi các sự kiện của cùng một lớp publisher. Bạn sẽ không muốn ghép publiser với tất cả các lớp đó. Bên cạnh đó, bạn thậm chí có thể không biết về một số trong số chúng trước nếu lớp publisher của bạn được người khác sử dụng. \n\nĐó là lý do tại sao cho việc tất cả subscriber phải triển khai cùng một interface và publisher chỉ giao tiếp với chúng qua interface đó. Interface này phải khai báo phương thức thông báo cùng với một tập hợp các tham số mà publisher có thể sử dụng để chuyển một số dữ liệu ngữ cảnh cùng với thông báo.\n\n![solution2](./assets/solution2.png)\n\nNếu ứng dụng của bạn có nhiều kiểu publisher khác nhau và bạn muốn làm cho subscriber của mình tương thích với tất cả chúng, bạn có thể tiến xa hơn nữa và khiến tất cả các publisher tuân theo cùng một interface. Interface này sẽ chỉ cần mô tả một số phương pháp đăng ký. Interface sẽ cho phép subscriber quan sát trạng thái của publisher mà không cần kết nối đến các lớp cụ thể của chúng.\n\n## 🚗 Thế Giới Thực\n\n![analogy](./assets/analogy.png)\n\nNếu bạn đăng ký một tờ báo hoặc tạp chí, bạn không cần phải đến cửa hàng để kiểm tra xem số tiếp theo có sẵn hay không. Thay vào đó, nhà xuất bản gửi các số báo mới trực tiếp đến hộp thư của bạn ngay sau khi xuất bản hoặc thậm chí trước.\n\nNhà xuất bản duy trì danh sách người đăng ký và biết họ quan tâm đến tạp chí nào. Người đăng ký có thể rời khỏi danh sách bất kỳ lúc nào khi họ muốn ngăn nhà xuất bản gửi các số tạp chí mới cho họ.\n\n## 🏢 Cấu trúc\n\n![structure](./assets/structure.png)\n\n1. **Publisher** phát hành các sự kiện mà các đối tượng khác quan tâm. Các sự kiện này diễn ra khi publisher thay đổi trạng thái của nó hoặc thực thi một vài hành vi. Publisher bao gồm một kết cấu đăng ký cho phép subscriber mới tham gia hay subscriber hiện tại rời khỏi danh sách.\n2. Khi một sự kiện mới diễn ra, publisher sẽ đi qua danh sách đăng ký và gọi phương thức thông báo được khai báo ở interface subscriber cho từng đối tượng subscriber.\n3. **Subscriber** là interface khai báo interface thông báo. Trong hầu hết trường hợp, nó bao gồm một phương thức cập nhật duy nhất. Phương thức này có nhiều tham số giúp publisher truyền một vài chi tiết sự kiện cùng với cập nhật.\n4. **Concrete Subscriber** thực hiện một vài hành động phản hồi lại thông báo được phát hành bởi publisher. Tất cả các lớp này phải triển khai cùng interface thế nên publisher không cần ghép với lớp cụ thể.\n5. Thông thường, subscriber cần một vài thông tin ngữ cảnh để xử lý cập nhật chính xác. Vì lý do này, publisher truyền một vài dữ liệu ngữ cảnh như các tham số cho phương thức thông báo. Publisher có thể truyền chính bản thân nó như một tham số, để subscriber có thể nạp bất kỳ dữ liệu cần thiết nào trực tiếp.\n6. **Client** tạo đối tượng publisher và subscriber riêng biệt, sau đó subscriber đăng ký các bản cập nhật publisher. \n\n## 👨‍💻 Mã giả\n\nTrong ví dụ này, Observer giúp trình soạn thảo thông báo cho các đối tượng dịch vụ về các thay đổi trạng thái.\n\n![pseudocode](./assets/pseudocode.png)\n\nDanh sách các subscriber được biên dịch động: đối tượng có thể bắt đầu hoặc kết thúc lắng nghe thông báo khi đang chạy, dựa trên hành vi mong muốn của ứng dụng.\n\nTrong triển khai này, lớp soạn thảo không duy trì danh sách đăng ký chính nó. Nó uỷ thác công việc cho đối tượng hỗ trợ đặc biệt làm điều đó. Bạn có thể nâng cấp đối tượng này để phục vụ như một trung tâm điều phối sự kiện, giúp bất kỳ đối tượng nào cũng hành động như một publisher.\n\nThêm các subscriber mới vào chương trình không yêu cầu thay đổi lớp publisher hiện có, miễn là chúng làm việc với subscriber thông qua cùng interface.\n\n```c\n// Lớp publisher cơ sở bao gồm code quản lý đăng ký\n// và phương thức thông báo.\nclass EventManager is\n    private field listeners: hash map of event types and listeners\n\n    method subscribe(eventType, listener) is\n        listeners.add(eventType, listener)\n\n    method unsubscribe(eventType, listener) is\n        listeners.remove(eventType, listener)\n\n    method notify(eventType, data) is\n        foreach (listener in listeners.of(eventType)) do\n            listener.update(data)\n\n// Publisher cụ thể bao gồm logic nghiệp vụ thực hấp dẫn một vài\n// subscriber. Ta có thể có dẫn xuất lớp này từ một publisher cơ\n// sở, nhưng điều này không luôn khả thi vì thực tế publisher cụ \n// thể sẽ có lớp con. Trong trường hợp này, ta có thể vá logic\n// đăng ký với composition.\nclass Editor is\n    public field events: EventManager\n    private field file: File\n\n    constructor Editor() is\n        events = new EventManager()\n\n    // Phương thức logic nghiệp vụ có thể thông báo subscriber\n    // về các thay đổi.\n    method openFile(path) is\n        this.file = new File(path)\n        events.notify(\"open\", file.name)\n\n    method saveFile() is\n        file.write()\n        events.notify(\"save\", file.name)\n\n    // ...\n\n\n// Đây là interface subscriber. Nếu ngôn ngữ lập trình của bạn\n// hỗ trợ kiểu function, bạn có thể thay thay toàn bộ hệ thống\n// phân cấp subscriber với một tập hợp function.\ninterface EventListener is\n    method update(filename)\n\n\n// Subscriber cụ thể phản ứng với bản cập nhật được phát hành\n// bởi publisher mà chúng được gắn.\nclass LoggingListener implements EventListener is\n    private field log: File\n    private field message: string\n\n    constructor LoggingListener(log_filename, message) is\n        this.log = new File(log_filename)\n        this.message = message\n\n    method update(filename) is\n        log.write(replace('%s',filename,message))\n\nclass EmailAlertsListener implements EventListener is\n    private field email: string\n    private field message: string\n\n    constructor EmailAlertsListener(email, message) is\n        this.email = email\n        this.message = message\n\n    method update(filename) is\n        system.email(email, replace('%s',filename,message))\n\n\n// Ứng dụng có thể cấu hình publisher và subscriber khi đang chạy\nclass Application is\n    method config() is\n        editor = new Editor()\n\n        logger = new LoggingListener(\n            \"/path/to/log.txt\",\n            \"Someone has opened the file: %s\")\n        editor.events.subscribe(\"open\", logger)\n\n        emailAlerts = new EmailAlertsListener(\n            \"admin@example.com\",\n            \"Someone has changed the file: %s\")\n        editor.events.subscribe(\"save\", emailAlerts)\n```\n\n## 💡 Ứng dụng\n\n**🐞 Sử dụng Observer khi thay đổi trạng thái của một đối tượng có thể yêu cầu thay đổi đối tượng khác, và tập hợp thực của đối tượng là không biết trước hoặc có thể thay đổi động**\n\n⚡ Bạn có thể gặp vấn đề này khi làm việc với lớp giao diện người dùng. Ví dụ, bạn tạo nhiều lớp button tuỳ chỉnh, và bạn muốn client kết nối với một vài tuỳ chỉnh code button của bạn để nó kích hoạt bất cứ khi nào người dùng click.\n\nObserver giúp bất kỳ đối tượng nào triển khai interface subscriber đăng ký nhận thông báo sự kiện ở đối tượng publisher. Bạn có thể thêm cơ chế subscription cho button của bạn, giúp client kết nối với code tuỳ chỉnh thông qua lớp subscriber tuỳ chỉnh.\n\n**🐞 Sử dụng Observer khi một vài đối tượng trong ứng dụng phải quan sát đối tượng khác, nhưng chỉ giới hạn thời gian và trường hợp cụ thể**\n\n⚡ Danh sách đăng ký là động, nên subscriber có thể tham gia hoặc rời danh sách khi chúng cần.\n\n## 📋 Triển khai\n\n1. Nhìn qua logic nghiệp vụ và chia nó làm hai phần: phần chức năng cốt lỗi độc lập với các phần khác, sẽ hành động như publisher. Phần còn lại sẽ là tập hợp lớp subscriber.\n\n2. Khai báo interface subscriber. Ở mức tối thiếu, nó nên có một phương thức cập nhật duy nhất.\n3. Khai báo interface publisher và mô tả một cặp phương thức cho thêm và xoá đối tượng subscriber khỏi danh sách. Hãy nhớ publisher phải làm việc với subscriber thông qua interface subscriber.\n4. Quyết định nơi đặt danh sách đăng ký và triển khai phương thức đăng ký. Thông thường, code này như nhau với tất cả kiểu publisher, thế nên nơi rõ ràng để đặt nó là lớp trừu tượng được lấy trực tiếp từ interface publisher. Publisher cụ thể mở rộng từ lớp này, kế thừa các hành vi đăng ký.\n    \n    Tuy nhiên, nếu bạn áp dụng pattern với hệ phân cấp lớp hiện có, bao gồm cách tiếp cận dựa trên composition: đặt logic đăng ký vào đối tượng riêng biệt, và để cho tất cả publisher sử dụng nó. \n5. Tạo lớp publisher cụ thể. Mỗi lần điều gì diễn ra trong publisher, sẽ phải thông báo cho tất cả subscriber.\n\n6. Triển khai phương thức thông báo cập nhật ở lớp subscriber cụ thể. Hầu hết subscriber sẽ cần dữ liệu ngữ cảnh về sự kiện. Nó có thể được truyền như một tham số cho phương thức thông báo.\n\n    Nhưng ở đây ta có lựa chọn khác. Khi nhận thông báo, subscriber có thể tìm nạp dữ liệu trực tiếp từ thông báo. Trong trường hợp này, publisher phải truyền bản thân nó thông qua phương thức cập nhật. Các lựa chọn kém linh hoạt hơn là liên kết publisher với subscriber vĩnh viễn qua hàm khởi tạo.\n\n7. Client phải tạo subscriber cần thiết và đăng ký nó với publisher phù hợp.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ *Open/Closed Principle*. Bạn có thể thêm lớp subscriber mới mà không ảnh hưởng đến code publisher (và ngược lại nếu có interface publisher).\n\n✔️ Bạn có thể thiết lập quan hệ giữa các đối tượng khi đang chạy.\n\n### Nhược điểm\n\n❌ Subscriber được thông báo theo thứ tự ngẫu nhiên. \n\n## 🔁 Quan hệ với các pattern khác\n\n**Chain of Responsibility**, **Command**, **Mediator** và **Observer** giải quyết các cách khác nhau để kết nối người gửi và người nhận yêu cầu:\n\n- **CoR** chuyển một yêu cầu tuần tự dọc theo một chuỗi động gồm những người nhận tiềm năng cho đến khi một trong số họ xử lý nó.\n- **Command** thiết lập các kết nối một chiều giữa người gửi và người nhận.\n- **Mediator** loại bỏ các kết nối trực tiếp giữa người gửi và người nhận, buộc họ phải giao tiếp gián tiếp thông qua một đối tượng trung gian.\n- **Observer** cho phép người nhận đăng ký động và hủy đăng ký nhận yêu cầu. \n\nSự khác biệt giữa **Mediator** và **Observer** thường khó nắm bắt. Trong hầu hết các trường hợp, bạn có thể triển khai một trong các pattern này; nhưng đôi khi bạn có thể áp dụng đồng thời cả hai. Hãy xem chúng ta có thể làm điều đó như thế nào.\n\n- Mục tiêu chính của **Mediator** là loại bỏ sự phụ thuộc lẫn nhau giữa một tập hợp các thành phần hệ thống. Thay vào đó, các thành phần này trở nên phụ thuộc vào một đối tượng mediator duy nhất. Mục tiêu của **Observer** là thiết lập các kết nối động một chiều giữa các đối tượng, nơi một số đối tượng đóng vai trò là cấp dưới của những đối tượng khác.\n\n- Có một cách triển khai phổ biến của **Mediator** vào **Observer**. Đối tượng mediator đóng vai trò là publisher và các thành phần đóng vai trò là subscribers, đăng ký và hủy đăng ký tham gia các sự kiện của mediator. Khi **Mediator** được triển khai theo cách này, nó có thể trông rất giống với **Observer**.\n\n- Nếu thấy bối rối, hãy nhớ rằng bạn có thể triển khai **Mediator** theo những cách khác. Ví dụ: bạn có thể liên kết vĩnh viễn tất cả các thành phần với cùng một đối tượng mediator. Việc triển khai này sẽ không giống với **Observer** nhưng vẫn sẽ là một bản sao của **Mediator**.\n\n- Bây giờ hãy tưởng tượng một chương trình mà tất cả các thành phần đã trở thành publisher, cho phép các kết nối động với nhau. Sẽ không có đối tượng mediator tập trung, chỉ có một nhóm observer phân tán.\n\n# Nguồn \n\n[refactoring](https://refactoring.guru/design-patterns/observer)\n"
  },
  {
    "path": "behavioral-pattern/state/README.md",
    "content": "# State\n\n## 📜 Mục đích\n\n**State** là một design pattern thuộc nhóm behavoiral giúp chỉnh sửa hành vi của một đối tượng khi trạng thái bên trong nó thay đổi. Nó xảy ra nếu như một đối tượng thay đổi lớp của nó.\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nPattern State có mối quan hệ gần gũi với khái niệm [Máy trạng thái hữu hạn](https://vi.wikipedia.org/wiki/Máy_trạng_thái_hữu_hạn) (gọi tắt là máy trạng thái)\n\n![problem1](./assets/problem1.png)\n\nÝ tưởng chính là như thế này, tại bất kỳ thời điểm nào cũng có một hữu hạn trạng thái mà chương trình có thể có. Với từng trạng thái đơn nhất, chương trình sẽ có hành vi khác nhau và chương trình còn có thể chuyển từ trạng thái này sang trạng thái khác ngay lập tức. Tuy nhiên, điều này phụ thuộc vào trạng thái hiện tại, mà chương trình có thể chuyển hoặc không thể chuyển sang trạng thái khác. Quy luật chuyển đổi này gọi là *transitions*, nó hữu hạn và có thể định trước.\n\nBạn có thể áp dụng cách tiếp cận này lên các đối tượng. Ví dụ bạn có lớp `Document`. Một tài liệu có thể có 3 trạng thái: `Draft`(nháp), `Moderation` (chờ duyệt) và `Published` (đã công khai). Phương thức `public` của tài liệu làm việc với từng trạng thái sẽ có vài khác biệt nhỏ:\n- Ở `Draft`, nó chuyển tài liệu lên chờ duyệt.\n- Ở `Moderation`, nó làm cho tài liệu công khai, nhưng chỉ khi người dùng hiện tại là admin.\n- Ở `Publushed` nó không phải làm gì cả.\n\n![problem2](./assets/problem2.png)\n\nMáy trạng thái thường được triển khai với nhiều điều kiện hành động (`if` hoặc `switch`) để lựa chọn hành vi thích hợp dựa trên trạng thái hiện tại của đối tượng. Thông thường, \"trạng thái\" này chỉ là một tập hợp trường giá trị của đối tượng. Nếu bạn đã từng nghe về *Máy trạng thái hữu hạn* trước đây, thì bạn có lẽ đã triển khai nó ít nhất một lần. Ví dụ như nhìn đoạn code dưới đây bạn có thấy quen quen không?\n\n```c\nclass Document is\n    field state: string\n    // ...\n    method publish() is\n        switch (state)\n            \"draft\":\n                state = \"moderation\"\n                break\n            \"moderation\":\n                if (currentUser.role == 'admin')\n                    state = \"published\"\n                break\n            \"published\":\n                // Do nothing.\n                break\n    // ...\n```\n\nĐiểm yếu lớn nhất của máy trạng thái nằm ở việc các điều kiện tự để lộ chúng khi ta thêm quá nhiều trạng thái và các hành vi phụ thuộc trạng thái vào lớp `Document`. Phần lớn phương thức sẽ chứa các điều kiện quái dị, để chọn hành vi phù hợp của phương thức theo trạng thái hiện tại. Điều này làm cho code trở nên khó bảo trì vì bất kỳ thay đổi nào đến logic transition sẽ đòi hỏi thay đổi điều kiện trạng thái ở toàn bộ phương thức.\n\nVấn đề có xu hướng trở nên lớn hơn khi dự án phát triển. Khá là khó khăn để có thể dự đoán tất cả trạng thái và transition xảy ra ở giai đoạn thiết kế. Do đó, một máy trạng thái tinh gọn được xây dựng với một tập hợp điều kiện giới hạn có thể phát triển thành một mớ hỗn độn theo thời gian. \n\n## 😊 Giải pháp\n\nState đề xuất giải pháp là tạo một lớp mới cho tất cả trạng thái của một đối tượng và trích xuất tất cả hành vi dựa trên trạng thái cụ thể vào lớp đó.\n\nThay vì triển khai tất cả hành vi của nó, đối tượng gốc bây giờ gọi là *context* sẽ lưu tham chiếu đến một trong những đối tượng trạng thái, để biểu diễn trạng thái hiện tại của nó và uỷ thác mọi công việc liên quan đến trạng thái cho đối tượng này.\n\n![solution](./assets/solution.png)\n\nĐể chuyển context sang trạng thái khác, ta sẽ thay thế đối tượng trạng thái đang hoạt động với một đối tượng khác để có trạng thái mới. Điều này chỉ khả thi khi tất cả lớp trạng thái theo cùng một interface và context làm việc với các đối tượng đó thông qua interface này.\n\nCấu trúc này trông giống Strategy, nhưng có một điểm khác biệt. Ở State, các trạng thái cụ thể có thể biết về nhau và bắt đầu chuyển đổi từ trạng thái này sang trạng thái khác, trong khi các Stategy hầu như không bao giờ biết về nhau\n\n## 🚗 Thế Giới Thực\n\nCác button và switch trong điện thoại thông minh của bạn hoạt động khác nhau tùy thuộc vào trạng thái hiện tại của thiết bị:\n\n- Khi điện thoại được mở khóa, việc nhấn các button dẫn đến việc thực hiện các chức năng khác nhau.\n- Khi điện thoại bị khóa, nhấn bất kỳ button nào sẽ dẫn đến màn hình mở khóa.\n- Khi điện thoại gần hết pin, nhấn bất kỳ button nào sẽ hiển thị màn hình sạc.\n\n## 🏢 Cấu trúc\n\n![structure](./assets/structure.png)\n\n1. **Context** lưu trữ một tham chiếu đến một trong các đối tượng concrete state và uỷ thác cho nó tất cả công việc cụ thể liên quan đến trạng thái. Context giao tiếp với đối tượng state thông qua interface state. Context để lộ một setter nhằm truyền vào nó một đối tượng state mới.\n2. **State** là interface khai báo phương thức cụ thể liên quan đến trạng thái. Phương thức này nên có nghĩa với tất cả concrete state vì bạn không muốn các trạng thái của bạn có một phương thức vô dụng không bao giờ dùng đến.\n3. **Concrete State** cung cấp triển khai của nó cho phương thức cụ thể liên quan đến trạng thái. Để tránh trùng lặp với code trên nhiều state, bạn nên cung cấp lớp trừu tượng trung gian cho đóng gói các hành vi dùng chung.\n\n    Đối tượng state có thể lưu trữ một tham chiếu trở lại (backreference) đến đối tượng context. Thông qua tham chiếu này, state có thể tìm nạp thông tin cần thiết từ đối tượng context, cũng như bắt đầu chuyển trạng thái. \n4. Cả context và concrete state có thể thiết lập trạng thái tiếp theo cho context và thực hiện chuyển đổi trạng thái thực bằng cách thay thế đối tượng state được liên kết với context.\n\n## 👨‍💻 Mã giả\n\nTrong ví dụ này, State sẽ làm cho cùng một bộ điều chỉnh nhạc có các hành vi khác nhau phụ thuộc vào trạng thái phát hiện tại.\n\n![pseudocode](./assets/pseudocode.png)\n\nĐối tượng chính của bộ phát nhạc có liên kết đến một đối tượng state, thứ thực hiện phần lớn công việc thực. Các hành động thay thế đối tượng state hiện tại của bộ phát nhạc bằng đối tượng khác, để thay đổi cách mà bộ phát nhạc phản ứng với tương tác của người dùng.\n\n```c\n// Lớp AudioPlayer hành động như một context. Nó luôn \n// duy trì tham chiếu đến một trong số các lớp state\n// để biểu diễn trạng thái hiện tại của bộ phát nhạc.\nclass AudioPlayer is\n    field state: State\n    field UI, volume, playlist, currentSong\n\n    constructor AudioPlayer() is\n        this.state = new ReadyState(this)\n\n        // Context uỷ thác việc xử lý đầu vào của người dùng\n        // cho đối tượng state. Kết quả dựa trên trạng thái\n        // hiện tại đang hoạt động, vì ở mỗi trạng thái sẽ xử\n        // lý đầu vào khác nhau.\n        UI = new UserInterface()\n        UI.lockButton.onClick(this.clickLock)\n        UI.playButton.onClick(this.clickPlay)\n        UI.nextButton.onClick(this.clickNext)\n        UI.prevButton.onClick(this.clickPrevious)\n\n\n    // Đối tượng khác có thể chuyển trạng thái hoạt động\n    // của bộ phát nhạc.\n    method changeState(state: State) is\n        this.state = state\n\n    // Các phương thức UI uỷ thác thực thi cho trạng thái\n    // đang hoạt động.\n    method clickLock() is\n        state.clickLock()\n    method clickPlay() is\n        state.clickPlay()\n    method clickNext() is\n        state.clickNext()\n    method clickPrevious() is\n        state.clickPrevious()\n\n    // State có thể gọi các phương thức dịch vụ có\n    // trên context\n    method startPlayback() is\n        // ...\n    method stopPlayback() is\n        // ...\n    method nextSong() is\n        // ...\n    method previousSong() is\n        // ...\n    method fastForward(time) is\n        // ...\n    method rewind(time) is\n        // ...\n\n\n// Lớp state cơ sở khai báo các phương thức cho tất cả concrete\n// state triển khai và cung cấp một tham chiếu trở về đối tượng \n// context được liên kết với state. Các state có thể dùng tham chiếu\n// đó để chuyển đổi trạng thái.\nabstract class State is\n    protected field player: AudioPlayer\n\n\n    // Context truyền chính nó qua hàm khởi tạo của state. Điều\n    // này giúp state lấy được dữ liệu hữu ích khi cần.\n    constructor State(player) is\n        this.player = player\n\n    abstract method clickLock()\n    abstract method clickPlay()\n    abstract method clickNext()\n    abstract method clickPrevious()\n\n\n// Các concrete state triển khai các hành vi khác nhau được \n// liên kết với state của context.\nclass LockedState extends State is\n\n\n    // Khi bạn mở khoá một bộ phát nhạc bị khoá,\n    // nó có thể có một trong hai trạng thái.\n    method clickLock() is\n        if (player.playing)\n            player.changeState(new PlayingState(player))\n        else\n            player.changeState(new ReadyState(player))\n\n    method clickPlay() is\n        // Bị khoá, nên không làm gì cả.\n\n    method clickNext() is\n        // Bị khoá, nên không làm gì cả.\n\n    method clickPrevious() is\n        // Bị khoá, nên không làm gì cả.\n\n\n// Chúng cũng có thể kích hoạt chuyển đổi trạng thái context.\nclass ReadyState extends State is\n    method clickLock() is\n        player.changeState(new LockedState(player))\n\n    method clickPlay() is\n        player.startPlayback()\n        player.changeState(new PlayingState(player))\n\n    method clickNext() is\n        player.nextSong()\n\n    method clickPrevious() is\n        player.previousSong()\n\n\nclass PlayingState extends State is\n    method clickLock() is\n        player.changeState(new LockedState(player))\n\n    method clickPlay() is\n        player.stopPlayback()\n        player.changeState(new ReadyState(player))\n\n    method clickNext() is\n        if (event.doubleclick)\n            player.nextSong()\n        else\n            player.fastForward(5)\n\n    method clickPrevious() is\n        if (event.doubleclick)\n            player.previous()\n        else\n            player.rewind(5)\n```\n\n## 💡 Ứng dụng\n\n**🐞 Sử dụng State khi bạn có một đối tượng có các hành vi khác nhau phụ thuộc vào trạng thái hiện tại, số lượng trạng thái là rất lớn và code của trạng thái cụ thể thường xuyên thay đổi**.\n \n⚡ Pattern đề nghị việc trích xuất tất cả code trạng thái cụ thể vào một tập hợp lớp riêng biệt. Kết quả là bạn có thể thêm trạng thái mới hoặc thay đổi cái đã có độc lập với nhau, giảm thiểu chi phí bảo trì.\n\n**🐞 Sử dụng State khi bạn có một lớp với số lượng điều kiện không lồ để thay đổi hành vi lớp đó theo giá trị hiện tại của các trường trong lớp đó.**\n\n⚡ State giúp bạn trích xuất các nhánh của các điều kiện này thành các phương thức của các lớp trạng thái tương ứng. Đồng thời bạn còn có thể làm sạch các trường tạm thời và các phương thức trợ giúp liên quan đến code trạng thái cụ thể khỏi lớp chính của bạn.\n\n**🐞 Sử dụng State khi bạn có một lượng lớn code trùng lặp các trạng thái và chuyển đổi tương tự của máy trạng thái dựa trên điều kiện.**\n\n⚡ State giúp bạn soạn các hệ thống phân cấp của các lớp trạng thái và làm giảm sự trùng lặp bằng cách trích xuất code chung vào lớp cơ sở trừu tượng.\n\n## 📋 Triển khai\n\n1. Xác định lớp nào sẽ hành động như context. Nó có thể là một lớp đã có sẵn hoặc một lớp mới, nếu code trạng thái cụ thể được phân phối trên nhiều lớp.\n2. Với tất cả trạng thái thực, tạo một lớp dẫn xuất từ interface state. Sau đó đi qua tất cả phương thức của context, trích xuất mọi code liên quan đến trạng thái vào lớp mới vừa tạo.\n3. Trong khi chuyển code vào lớp trạng thái, bạn sẽ gặp trường hợp là nó phụ thuộc vào thành phần riêng tư của context. Có một vài cách giải quyết là:\n    - Làm cho trường hay phương thức đó công khai.\n    - Chuyển hành vi bạn đang trích xuất vào phương thức công khai trong context và gọi nó từ lớp state. Cách này khá tệ nhưng nhanh bạn có thể sửa lại sau.\n    - Lồng lớp state vào lớp context, nhưng chỉ khi ngôn ngữ lập trình của bạn hỗ trợ lớp lồng nhau.\n4. Trong lớp context, thêm trường tham chiếu của kiểu interface state và một setter công khai cho phép ghi đè giá trị lên trường.\n5. Đi qua phương thức của context lần nữa và thay thế điều kiện trạng thái trống với lệnh gọi đến phương thức phù hợp của đối tượng state.\n6. Để chuyển đổi trạng thái context, tạo một trong những lớp state và truyền nó vào context. Bạn có thể làm điều này bên trong context hoặc các state khác, hoặc ở client. Bất cứ khi nào thực hiện xong, lớp sẽ trở nên phụ thuộc vào lớp concrete state mà nó khởi tạo.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ *Single Responsibility Principle*. Tổ chức code liên kết với trạng thái cụ thể trong lớp riêng biệt.\n\n✔️ *Open/Closed Principle*. Thêm trạng thái mới mà không ảnh hưởng đến lớp trạng thái hiện có hay ngữ cảnh.\n\n✔️ Đơn giản hoá code context bằng loại bỏ các điều kiện máy trạng thái cồng kềnh.\n\n### Nhược điểm\n\n❌ Việc áp dụng pattern có thể quá mức cần thiết nếu máy trạng thái chỉ có một vài trạng thái hoặc hiếm khi thay đổi.\n\n## 🔁 Quan hệ với các pattern khác\n\n**Bridge**, **State**, **Strategy** (và ở một mức độ nào đó là **Adapter**) có cấu trúc rất giống nhau. Thật vậy, tất cả các pattern này đều dựa trên nguyên tắc là ủy thác công việc cho các đối tượng khác. Tuy nhiên, chúng giải quyết các vấn đề khác nhau. Một pattern không chỉ là một công thức để cấu trúc code của bạn theo một cách cụ thể. Nó còn có thể truyền đạt đến các dev khác về vấn đề mà pattern giải quyết.\n\n**State** có thể được coi là một phần mở rộng của **Strategy**. Cả hai pattern đều dựa trên kết hợp: chúng thay đổi hành vi của ngữ cảnh bằng cách ủy quyền một số công việc cho các đối tượng trợ giúp. **Strategy** làm cho các đối tượng này hoàn toàn độc lập và không biết về nhau. Tuy nhiên, **State** không hạn chế sự phụ thuộc giữa các trạng thái cụ thể, cho phép chúng thay đổi trạng thái của ngữ cảnh theo ý muốn.\n\n# Nguồn\n\n[**refactoring**](https://refactoring.guru/design-patterns/state)"
  },
  {
    "path": "behavioral-pattern/strategy/README.md",
    "content": "# Strategy\n\n## 📜 Mục đích\n\n**Strategy** là một design pattern thuộc nhóm behavioral giúp bạn xác định một nhóm thuật toán, đặt chúng vào một lớp riêng biệt và làm cho các đối tượng của chúng có thể hoán đổi lẫn nhau.\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nVào một ngày đẹp trời, bạn định tạo một ứng dụng chỉ đường cho các khách du lịch. Ứng dụng xoay quanh các bản đồ đẹp mắt giúp người dùng dễ dàng đi đến bất cứ thành phố nào.\n\nPhần lớn chức năng yêu cầu của ứng dụng là tự thiết lập lộ trình đường đi. Người dùng sẽ nhập vào địa chỉ hiện tại của họ và thấy con đường nhanh nhất để đến đích trên bản đồ.\n\nPhiên bản đầu tiên của ứng dụng chỉ tập trung vào những đại lộ. Những người du lịch bằng xe sẽ cảm thấy vui sướng vì điều này. Nhưng mà rõ ràng là, không phải tất cả mọi người đều du lịch bằng xe. Thế nên ở bản cập nhật tiếp theo, bạn thêm tính năng chức năng cho người đi bộ. Ngay sau đó, bạn thêm các lựa chọn khác cho những phương tiện công cộng(bus, tàu điện ngầm,..) trên tuyến đường của họ.\n\nTuy nhiên, mọi thứ vẫn chưa dừng lại. Sau đó bạn định thêm lộ trình cho người đi xe đạp, hay là về sau này bạn sẽ thêm các lựa chọn khác cho xây dựng các lộ trình qua tất cả điểm tham quan trong thành phố.\n\n![problem](./assets/problem.png)\n\nTừ quan điểm kinh doanh, ứng dụng của bạn đã thành công, nhưng ở khía cạnh kỹ thuật bạn sẽ gặp nhiều vấn đề đau đầu. Mỗi lần bạn thêm một thuật toán chỉ đường mới, lớp chính của bộ chỉ đường sẽ gấp đôi kích thước. Và đến một thời điểm nào đó, nó sẽ như là một con quái vật, cực kỳ khó cho việc bảo trì.\n\nBất kỳ một thuật toán nào thay đổi, cho dù chỉ là fix lỗi đơn giản hay một chút điều chỉnh lên các con đường nó cũng ảnh hưởng đến toàn bộ lớp, làm tăng nguy cơ sinh lỗi ở các đoạn code đã hoạt động.\n\nBên cạnh đó, teamwork cũng bất tiện hơn. Các đồng nghiệp của bạn, những người gia nhập sau khi phiên bản đầu tiên phát hành sẽ than phiền rằng họ mất quá nhiều thời gian cho giải quyết các xung đột khi hợp nhất. Triển khai tính năng mới yêu cầu thay đổi cùng một lớp khổng lồ, xung đột với code được viết bởi những người khác.\n\n## 😊 Giải pháp\n\nStrategy đề xuất giải pháp là bạn nên chọn một lớp làm điều gì đó cụ thể theo nhiều cách khác nhau và trích xuất tất cả thuật toán vào các lớp riêng biệt đấy gọi là *strategy*.\n\nLớp gốc gọi là context, phải có một trường lưu trữ tham chiếu đến một trong các stategy. Context uỷ thác công việc cho đối tượng strategy được liên kết thay vì tự thực hiện nó.\n\nContext không có trách nhiệm chọn thuật toán phù hợp cho công việc. Thay vào đó, client truyền strategy mong muốn đến context. Thực tế, context không biết gì về strategy. Nó làm việc với mọi strategy thông qua interface chung, nó chỉ để lộ một phương thức duy nhất cho kích hoạt thuật toán đã đóng gói trong stategy được chọn.\n\nVới cách này, context trở nên độc lập với các strategy cụ thể, bạn có thể thêm hay chỉnh sửa thuật toán mà không ảnh hưởng gì đến code của context hay các strategy khác.\n\n![solution](./assets/solution.png)\n\nTrở lại với ứng dụng chỉ đường, mội thuật toán định tuyến có thể được trích xuất vào lớp của chúng với phương thức `buildRoute` duy nhất. Phương thức nhận vào điểm đầu và đích đến, và trả về một tập hợp các trạm dừng của lộ trình.\n\nMặc dùng cho cùng một tham số, mỗi lớp định tuyến sẽ có tạo một lộ trình khác nhau, lớp chính của ứng dụng không thực sự quan tâm thuật toán được chọn vì công việc chính của nó chỉ là hiển thị các trạm dừng trên bản đồ. Lớp có phương thức chuyển đổi các lịch trình đang hoạt động, thế nên người dùng với các button ở giao diện người dùng, có thể thay thế hành vi được chọn hiện tại với cái khác.\n\n## 🚗 Thế Giới Thực\n\n![analogy](./assets/analogy.png)\n\nTưởng tượng để đi đến sân bay. Bạn có thể bắt xe bus, gọi taxi hay đi xe đập. Các phương tiện của bạn là strategy. Bạn có thể chọn một trong các strategy dựa vào các nhân tố như ví tiền hay thời gian.\n\n## 🏢 Cấu trúc\n\n![structure](./assets/structure.png)\n\n1. **Context** duy trì một tham chiếu đến một trong các strategy cụ thể và giao tiếp với các đối tượng này thông qua interface strategy.\n2. **Strategy** là interface chung cho tất cả strategy cụ thể. Nó khai báo một phương thức duy nhất cho context sử dụng để thực thi.\n3. **Concrete Strategies** triển khai khác nhau của thuật toán mà context sử dụng.\n4. Context gọi phương thức thực thi đến đối tượng strategy được liên kết mỗi lần nó cần chạy thuật toán. Context không cần biết chính xác kiểu strategy nào đang làm việc và thuật toán được thực thi thế nào.\n5. **Client** tạo đối tượng strategy cụ thể và truyền nó vào context. Context để lộ một setter cho client thay thế với strategy được liên kết với context khi đang chạy.\n\n## 👨‍💻 Mã giả\n\nTrong ví dụ này, context sử dụng nhiều strategy để thực hiện các phép toán khác nhau.\n\n```c\n// Interface strategy khai báo các phép toán chung cho tất cả \n// phiên bản hỗ trợ của một vài thuật toán. Context sử dụng \n// interface này để gọi thuật toán đã xác định bởi concrete\n// strategies.\ninterface Strategy is\n    method execute(a, b)\n\n// Concrete strategies triển khai thuật toán khi đang theo\n// interface strategy cơ sở. Interface hoán đổi chúng với\n// nhau trong context.\nclass ConcreteStrategyAdd implements Strategy is\n    method execute(a, b) is\n        return a + b\n\nclass ConcreteStrategySubtract implements Strategy is\n    method execute(a, b) is\n        return a - b\n\nclass ConcreteStrategyMultiply implements Strategy is\n    method execute(a, b) is\n        return a * b\n\n// Context xác định interface mà client mong muốn.\nclass Context is\n    // Context duy trì một tham chiếu đến một trong các đối tượng\n    // strategy. Context không biết rõ lớp cụ thể của strategy. \n    // Nó làm việc với mọi strategy thông qua interface strategy.\n    private strategy: Strategy\n\n\n    // Thông thường, context nhận strategy thông qua hàm khởi\n    // tạo và cung cập một setter cho strategy có thể chuyển\n    // đổi khi đang chạy.\n    method setStrategy(Strategy strategy) is\n        this.strategy = strategy\n\n\n    // Context uỷ thác công việc cho đối tượng strategy thay\n    // vì triển khai nhiều phiên bản thuật toán của chính nó.\n    method executeStrategy(int a, int b) is\n        return strategy.execute(a, b)\n\n\n// Code client chọn một concrete strategy và truyền nó vào \n// context. Client nên nhận thức được sự khác nhau giữa \n// các strategy theo trật tự để chọn đúng.\nclass ExampleApplication is\n    method main() is\n        Create context object.\n\n        Read first number.\n        Read last number.\n        Read the desired action from user input.\n\n        if (action == addition) then\n            context.setStrategy(new ConcreteStrategyAdd())\n\n        if (action == subtraction) then\n            context.setStrategy(new ConcreteStrategySubtract())\n\n        if (action == multiplication) then\n            context.setStrategy(new ConcreteStrategyMultiply())\n\n        result = context.executeStrategy(First number, Second number)\n\n        Print result.\n```\n\n## 💡 Ứng dụng\n\n**🐞 Sử dụng Strategy khi bạn muốn dùng các biến thể thuật toán khác nhau trong một đối tượng cho phép chuyển đổi từ thuật toán này sang thuật toán khác khi đang chạy**.\n \n⚡ Strategy giúp bạn gián tiếp chỉnh sửa hành vi của đối tượng khi đang chạy bằng liên kết với các đối tượng con khác để thực hiện hành vi cụ thể theo các cách khác nhau.\n\n**🐞 Sử dụng Strategy khi bạn có nhiều lớp giống nhau chỉ khác nhau cách chúng thực hiện một vài hành vi**\n\n⚡ Strategy giúp bạn trích xuất các hành vi khác nhau vào một hệ thống phân cấp lớp và kết hợp với lớp gốc thành một, bằng cách này sẽ làm giảm code trùng lặp.\n\n**🐞 Sử dụng Strategy để cô lập logic nghiệp vụ của một lớp khỏi triển khai chi tiết của thuật toán, thứ không mấy quan trọng trong ngữ cảnh của logic đó**.\n\n⚡ Strategy giúp bạn cô lập code, dữ liệu bên trong và các phụ thuộc vào thuật toán với phần code còn lại. Các client khác nhau nhận về một interface đơn giản để thực thi thuật toán và chuyển đổi chúng khi đang chạy.\n\n**🐞 Sử dụng Strategy khi lớp của bạn có một lượng điều kiện khổng lồ để chuyển đổi các biến thể khác nhau với cùng thuật toán**.\n\n⚡ Strategy giúp bạn bỏ đi các điều kiện bằng cách trích xuất tất cả thuật toán vào các lớp riêng biệt. Toàn bộ triển khai cùng interface. Đối tượng gốc uỷ thác thực thi cho một trong các đối tượng trên thay vì triển khai tất cả biến thể của thuật toán.\n\n## 📋 Triển khai\n\n1. Trong lớp context, xác định thuật toán dễ thay đổi. Nó còn có thể có một lượng lớn điều kiện để chọn và thực thi một biến thể của cùng một thuật toán khi đang chạy\n2. Khai báo interface strategy chung cho tất cả biến thể của thuật toán.\n3. Từng cái một, trích xuất tất cả thuật toán vào các lớp của nó. Chúng nên triển khai tất cả trên interface strategy.\n4. Trong lớp context, thêm một trường cho lưu trữ tham chiếu đến đối tượng strategy. Cung cấp một setter cho thay thế giá trị của trường này. Context nên làm việc với đối tượng strategy thông qua interface strategy. Context có thể định nghĩa một interface để cho phép strategy truy cập dữ liệu của nó.\n5. Client của context phải liên kết nó với strategy phù hợp để ứng với cách chúng mong đợi context thực hiện hành vi chính.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ Bạn có thể chuyển đổi thuật toán bên trong đối tượng khi đang chạy.\n\n✔️ Bạn có thể cô lập triển khai chi tiết của thuật toán khỏi code sử dụng nó.\n\n✔️ Bạn có thể thay thế kế thừa với hỗn hợp.\n\n✔️ *Open/Closed Principle*. Bạn có thể thêm strategy mới mà không ảnh hưởng đến context.\n\n### Nhược điểm\n\n❌ Nếu bạn chỉ có một vài thuật toán và chúng hiếm khi thay đổi, thì không có lý do thực sự nào để làm phức tạp chương trình quá mức với các lớp và interface mới đi kèm với pattern.\n\n❌ Client phải nhận thức được các strategy khác nhau để có thể chọn cái phù hợp.\n\n❌ Rất nhiều ngôn ngữ lập trình hiện đại có hỗ trợ kiểu hàm cho phép bạn triển khai các phiên bản khác nhau của thuật toán bên trong một tập hợp các hàm ẩn danh. Sau đó, bạn có thể sử dụng các chức năng này chính xác như khi bạn đã sử dụng các đối tượng strategy, nhưng không làm tăng code của bạn với các lớp và giao diện bổ sung.\n\n## 🔁 Quan hệ với các pattern khác\n\n**Bridge**, **State**, **Strategy** (và ở một mức độ nào đó là **Adapter**) có cấu trúc rất giống nhau. Thật vậy, tất cả các pattern này đều dựa trên nguyên tắc là ủy thác công việc cho các đối tượng khác. Tuy nhiên, chúng giải quyết các vấn đề khác nhau. Một pattern không chỉ là một công thức để cấu trúc code của bạn theo một cách cụ thể. Nó còn có thể truyền đạt đến các dev khác về vấn đề mà pattern giải quyết.\n\n**Command** và **Strategy** có thể trông giống nhau vì bạn có thể sử dụng cả hai để tham số hóa một đối tượng bằng một số hành động. Tuy nhiên, chúng có mục đích rất khác nhau.\n\n- Bạn có thể sử dụng **Command** để chuyển đổi bất kỳ thao tác nào thành một đối tượng. Các tham số của thao tác trở thành các trường của đối tượng đó. Việc chuyển đổi cho phép bạn trì hoãn việc thực hiện thao tác, xếp hàng đợi, lưu trữ lịch sử lệnh, gửi lệnh đến các dịch vụ từ xa, v.v.\n\n- Mặt khác, **Strategy** thường mô tả các cách khác nhau để thực hiện cùng một việc, cho phép bạn hoán đổi các thuật toán này trong một lớp ngữ cảnh duy nhất.\n\n**Decorator** cho phép bạn thay đổi vẻ ngoài của một đối tượng, trong khi **Strategy** cho phép bạn thay đổi ruột.\n\n**Template Method** dựa trên sự kế thừa: nó cho phép bạn thay đổi các phần của một thuật toán bằng cách mở rộng các phần đó trong các lớp con. **Strategy** dựa trên cấu tạo: bạn có thể thay đổi các phần trong hành vi của đối tượng bằng cách cung cấp cho đối tượng các strategy khác nhau tương ứng với hành vi đó. **Template Method** hoạt động ở cấp độ lớp, vì vậy nó là tĩnh. **Strategy** hoạt động ở cấp độ đối tượng, cho phép bạn chuyển đổi hành vi trong thời gian chạy.\n\n**State** có thể được coi là một phần mở rộng của **Strategy**. Cả hai pattern đều dựa trên kết hợp: chúng thay đổi hành vi của ngữ cảnh bằng cách ủy quyền một số công việc cho các đối tượng trợ giúp. **Strategy** làm cho các đối tượng này hoàn toàn độc lập và không biết về nhau. Tuy nhiên, **State** không hạn chế sự phụ thuộc giữa các trạng thái cụ thể, cho phép chúng thay đổi trạng thái của ngữ cảnh theo ý muốn.\n\n# Nguồn\n\n[**refactoring**](https://refactoring.guru/design-patterns/strategy)"
  },
  {
    "path": "behavioral-pattern/template-method/README.md",
    "content": "# Template Method\n\n## 📜 Mục đích\n\n**Template Method** là một design pattern thuộc nhóm behavioral giúp định nghĩa bộ khung của thuật toán ở lớp cha (superclass) nhưng các lớp con (subsclasses) có thể ghi đè lên các bước cụ thể của thuật toán mà không làm thay đổi cấu trúc của nó.\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nTưởng tượng bạn đang tạo một ứng dụng khai thác dữ liệu để phân tích tài liệu của công ty. Người dùng cung cấp các tài liệu cho ứng dụng với các định dạng khác nhau (PDF, DOC, CSV), ứng dụng sẽ trích xuất dữ liệu có ích từ các tài liệu này ở một định dạng thống nhất.\n\nPhiên bản đầu tiên của ứng dụng chỉ làm việc với file DOC. Trong phiên bản tiếp theo nó hỗ trợ file CSV. Và một tháng sau, nó trích xuất cả dữ liệu từ file PDF.\n\n![problem](./assets/problem.png)\n\nVào một thời điểm nào đó, bạn nhận thấy rằng cả code ở cả ba lớp có rất nhiều điểm tương đồng nhau. Mặc dù code để xử lý các định dạng dữ liệu khác nhau hoàn toàn khác nhau ở tất cả các lớp, nhưng code để xử lý và phân tích dữ liệu gần như giống hệt nhau. Sẽ rất tuyệt vời nếu ta có thể loại bỏ sự trùng lặp code nhưng vẫn giữ nguyên được cấu trúc của thuật toán.\n\nVà một vấn đề khác nữa liên quan đến code client, nơi sử dụng các lớp này, là nó có rất nhiều điều kiện để chọn quá trình hành động thích hợp tùy thuộc vào lớp của đối tượng xử lý. Nếu cả ba lớp xử lý đều có một interface chung hoặc một lớp cơ sở, bạn có thể loại bỏ các điều kiện trong code client và sử dụng tính đa hình khi gọi các phương thức trên một đối tượng xử lý.\n\n## 😊 Giải pháp\n\nTemplate Method gợi ý rằng bạn nên chia nhỏ thuật toán thành một chuỗi các bước, biến các bước này thành các phương thức và đặt một loạt lệnh gọi đến các phương thức này bên trong một phương thức template duy nhất. Các bước có thể là `abstract` (trừu tượng) hoặc có một số triển khai mặc định. Để sử dụng thuật toán, client phải cung cấp lớp con của chính nó, thực hiện tất cả các bước trừu tượng và ghi đè một số bước tùy chọn nếu cần (nhưng không được ghi lên phương thức template).\n\nHãy xem cách nó làm việc trong ứng dụng khai thác dữ liệu. Ta có thể tạo một lớp cơ sở cho cả ba thuật toán phân tích. Lớp này định nghĩa một phương thức template bao gồm một loạt các lệnh gọi đến các bước xử lý tài liệu khác nhau.\n\n![solution](./assets/solution.png)\n\nLúc đầu, ta có thể khai báo tất cả các bước là `abstract`, buộc các lớp con cung cấp các triển khai riêng của chúng cho các phương thức này. Trong trường hợp này, các lớp con đã có tất cả các triển khai cần thiết, vì vậy điều duy nhất ta cần làm là điều chỉnh signature của các phương thức để phù hợp với các phương thức của lớp cha.\n\nBây giờ, hãy xem cách để có thể loại bỏ code trùng lặp. Có thể thấy code để mở/đóng file và trích xuất/phân tích dữ liệu là khác nhau đối với các định dạng dữ liệu khác nhau, vì vậy bạn không cần phải đụng đến các phương pháp đó. Tuy nhiên, việc thực hiện các bước khác, chẳng hạn như phân tích dữ liệu raw và soạn báo cáo, rất giống nhau, vì vậy nó có thể được kéo lên lớp cơ sở, nơi các lớp con có thể chia sẻ code đó.\n\nNhư bạn có thể thấy, ta có hai loại bước:\n\n- các bước trừu tượng phải được thực hiện bởi mọi lớp con.\n- các bước tùy chọn đã có một số triển khai mặc định, nhưng vẫn có thể bị ghi đè nếu cần.\n\nCó một loại bước khác, được gọi là hook. Hook là một bước tùy chọn với phần thân trống. Phương thức template sẽ hoạt động ngay cả khi hook không bị ghi đè. Thông thường, các hook được đặt trước và sau các bước quan trọng của thuật toán, cung cấp các lớp con với các điểm mở rộng bổ sung cho một thuật toán.\n\n## 🚗 Thế Giới Thực\n\n![analogy](./assets/analogy.png)\n\nPhương pháp template có thể được sử dụng trong xây dựng hàng loạt ngôi nhà. Kế hoạch kiến trúc để xây dựng một ngôi nhà tiêu chuẩn có thể chứa một số điểm mở rộng cho phép người chủ sở hữu có tiềm năng điều chỉnh một số chi tiết của ngôi nhà.\n\nMỗi công đoạn xây dựng như đổ móng, đóng khung, xây tường, lắp đặt hệ thống ống nước, đi dây điện nước,… đều có thể thay đổi đôi chút để tạo cho ngôi nhà có một chút khác biệt so với những ngôi nhà khác.\n\n## 🏢 Cấu trúc\n\n![structure](./assets/structure.png)\n\n1. **Abstract Class** là lớp trừu tượng khai báo các phương thức hoạt động như các bước của một thuật toán, cũng như phương thức template để gọi các phương thức này theo một thứ tự cụ thể. Các bước có thể được khai báo là trừu tượng hoặc có một số triển khai mặc định.\n2. **Concrete Classes** có thể ghi đè tất cả các bước, nhưng không thể ghi đè lên phương thức template.\n\n## 👨‍💻 Mã giả\n\nTrong ví dụ này, phương thức Template cung cấp một \"bộ khung\" cho các branch khác nhau của trí thông minh nhân tạo trên một trò chơi điện tử mô phỏng đơn giản.\n\n![pseudocode](./assets/pseudocode.png)\n\nTất cả chủng tộc trong trò chơi gần như giống nhau về kiểu unit và cách xây dựng. Do đó bạn có thể sử dụng lại cùng một cấu trúc AI cho các chủng tộc khác nhau, đồng thời vẫn có thể ghi đè lên một vài chi tiết. Với cách tiếp cận này, bạn có thể ghi đè lên AI của loài orc làm cho chúng hung dữ, làm cho loài người có khả năng phòng thủ và lũ quái vật không thể xây dựng bất kỳ thứ gì. Thêm một chủng tộc mới trong game yêu cầu tạo một lớp con AI mới và ghi đè lên phương thức mặc định đã tạo ở lớp AI cơ sở.\n\n```c\n// Lớp abstract định nghĩa một phương thức template bao gồm\n// bộ khung của một vài thuật toán được gọi, thông thường là\n// các thao tác nguyên thuỷ trừu tượng. Concrete subclass triển\n// khai các thao tác này, nhưng vẫn giữ nguyên phương thức\n// template.\nclass GameAI is\n    // Phương thức template định nghĩa khung của một thuật toán.\n    method turn() is\n        collectResources()\n        buildStructures()\n        buildUnits()\n        attack()\n\n\n    // Một vài bước có thể triển khai ở tại lớp cơ sở.\n    method collectResources() is\n        foreach (s in this.builtStructures) do\n            s.collect()\n\n    // Và một số có thể định nghĩa là trừu tượng.\n    abstract method buildStructures()\n    abstract method buildUnits()\n\n    // Một lớp có thể có nhiều phương thức template.\n    method attack() is\n        enemy = closestEnemy()\n        if (enemy == null)\n            sendScouts(map.center)\n        else\n            sendWarriors(enemy.position)\n\n    abstract method sendScouts(position)\n    abstract method sendWarriors(position)\n\n\n// Concrete class phải triển khai tất cả thao tác trừu tượng \n// của lớp cơ sở và không được ghi đè lên phương thức template.\nclass OrcsAI extends GameAI is\n    method buildStructures() is\n        if (there are some resources) then\n            // Xây dựng trang trại, sau đó là doanh trại, sau đó là thành trì.\n            \n    method buildUnits() is\n        if (there are plenty of resources) then\n            if (there are no scouts)\n                // Xây dựng người liên lạc, thêm nó vào nhóm trinh sát.\n            else\n                // Xây dựng grunt, thêm nó vào nhóm chiến binh.\n                \n    // ...\n\n    method sendScouts(position) is\n        if (scouts.length > 0) then\n            // Cử trinh sát đến vị trí.\n\n    method sendWarriors(position) is\n        if (warriors.length > 5) then\n            // Đưa chiến binh vào vị trí.\n\n\n// Lớp con có thể ghi đè một vài thao tác với\n// triển khai mặc định.\nclass MonstersAI extends GameAI is\n    method collectResources() is\n        // Quái vật không thể thu thập tài nguyên.\n\n    method buildStructures() is\n        // Quái vật không thể xây dựng kiến trúc..\n\n    method buildUnits() is\n        // Quái vật không thể xây dựng đơn vị.\n```\n\n## 💡 Ứng dụng\n\n**🐞 Sử dụng phương thức Template khi bạn muốn client chỉ mở rộng các bước cụ thể của thuật toán chứ không phải toàn bộ cấu trúc của nó**\n\n⚡ Phương thức Template giúp bạn chuyển một khối thuật toán thành một loạt các bước riêng rẽ để dễ mở rộng bởi lớp con trong khi vẫn giữ nguyên cấu trúc đã định nghĩa ở lớp cha.\n\n**🐞 Sử dụng template khi bạn có nhiều lớp bao gồm các thuật toán giống nhau chỉ có một ít là khác biệt. Và bạn phải chỉnh sửa tất cả lớp khi thuật toán thay đổi**.\n\n⚡ Khi bạn chuyển một thuật toán thành phương thức template, bạn có thể kéo các bước với triển khai giống nhau lên lớp cha, giảm thiểu code trùng lặp. Code khác nhau ở lớp con có thể được giữ lại ở đấy.\n\n## 📋 Triển khai\n\n1. Phân tích thuật toán mục tiêu để xem liệu bạn có thể chia nó thành các bước hay không. Xem xét bước nào là chung cho tất cả các lớp con và bước nào là duy nhất.\n2. Tạo lớp trừu tường (`abstract`) và khai báo phương thức template và một tập hợp của phương thức trừu tượng để biểu diễn các bước của thuật toán. Phác thảo cấu trúc của thuật toán trong phương pháp template bằng cách thực hiện các bước tương ứng. Cân nhắc việc tạo phương thức template cuối cùng để ngăn các lớp con ghi đè nó.\n3. Sẽ không sao nếu tất cả các bước đều trừu tượng. Tuy nhiên, một số bước có thể được hưởng lợi từ việc triển khai mặc định. Các lớp con không phải triển khai các phương thức đó.\n4. Thêm hook giữa các bước cốt lõi của thuật toán.\n5. Đối với mỗi biến thể của thuật toán, hãy tạo một lớp con cụ thể(concrete subclasses) mới. Nó phải triển khai tất cả các bước trừu tượng, nhưng cũng có thể ghi đè một số bước tùy chọn.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ Bạn chỉ cho phép client ghi đè một số phần nhất định của một thuật toán lớn, giúp chúng ít bị ảnh hưởng bởi những thay đổi xảy ra với các phần khác của thuật toán.\n\n✔️ Bạn có thể gom code trùng lặp vào một lớp cha.\n\n### Nhược điểm\n\n❌ Một số client có thể bị giới hạn bởi khung thuật toán được cung cấp.\n\n❌ Bạn có thể vi phạm Nguyên tắc Liskov Substitution, khi chặn triển khai bước mặc định thông qua một lớp con.\n\n❌ Các phương pháp template có xu hướng khó bảo trì hơn khi chúng có nhiều bước hơn.\n\n## 🔁 Quan hệ với các pattern khác\n\n**Factory Method** là một chuyên môn hóa của **Template Method**. Đồng thời, **Factory Method** có thể đóng vai trò là một bước trong một **Template Method** lớn.\n\n**Template Method** dựa trên sự kế thừa: nó cho phép bạn thay đổi các phần của một thuật toán bằng cách mở rộng các phần đó trong các lớp con. **Strategy** dựa trên cấu tạo: bạn có thể thay đổi các phần trong hành vi của đối tượng bằng cách cung cấp cho đối tượng các strategy khác nhau tương ứng với hành vi đó. **Template Method** hoạt động ở cấp độ lớp, vì vậy nó là tĩnh. **Strategy** hoạt động ở cấp độ đối tượng, cho phép bạn chuyển đổi hành vi trong thời gian chạy.\n\n# Nguồn\n\n[**refactoring**](https://refactoring.guru/design-patterns/template-method)"
  },
  {
    "path": "behavioral-pattern/visitor/README.md",
    "content": "# Visitor\n\n## 📜 Mục đích\n\n**Visitor** là một design pattern thuộc nhóm behavioral giúp bạn tách các thuật toán khỏi đối tượng mà chúng đang hoạt động trên đó.\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nTưởng tượng team bạn đang phát triển một ứng dụng làm việc với thông tin địa lý được cấu trúc dưới dạng một đồ thị khổng lồ. Mỗi nút trong đồ thị có thể biểu diễn một thực thể phức tạp như một thành phố, nhưng chi tiết hơn như các nhà máy, khu tham quan,... Các nút được kết nối với nhau nếu có một con đường giữa các đối tượng thực mà nó biểu diễn. Hiểu sâu hơn, mỗi loại nút được biểu diễn bởi lớp riêng của nó, trong khi mỗi nút cụ thể là một đối tượng.\n\n![problem](./assets/problem1.png)\n\nTại một thời điểm nào đó, bạn có nhiệm vụ xuất đồ thị sang định dạng XML. Lúc đầu, công việc có vẻ khá đơn giản. Bạn đã lên kế hoạch thêm một phương thức xuất vào từng lớp nút và sau đó tận dụng đệ quy để đi qua từng nút của đồ thị, thực hiện phương thức xuất. Giải pháp rất đơn giản và gọn gàng: nhờ tính đa hình, bạn không phải ghép đoạn code phương thức xuất với các lớp nút cụ thể.\n\nThật không may, kỹ sư hệ thống đã từ chối cho phép bạn thay đổi các lớp nút hiện có. Anh ấy nói rằng code đã được tạo và anh ấy không muốn mạo hiểm phá vỡ nó vì một lỗi tiềm ẩn trong các thay đổi của bạn.\n\n![problem](./assets/problem2.png)\n\nBên cạnh đó, anh ấy đặt câu hỏi liệu có hợp lý khi có code xuất XML trong các lớp nút hay không. Công việc chính của các lớp này là làm việc với dữ liệu địa lý. Hành vi xuất XML sẽ có vẻ không phù hợp ở đó.\n\nCó một lý do khác cho việc từ chối. Rất có thể sau khi tính năng này được triển khai, một người nào đó từ bộ phận tiếp thị sẽ yêu cầu bạn cung cấp khả năng xuất sang một định dạng khác hoặc yêu cầu một số thứ kỳ lạ khác. Điều này sẽ buộc bạn phải thay đổi những lớp này một lần nữa.\n\n## 😊 Giải pháp\n\nPattern Visitor gợi ý rằng bạn nên đặt hành vi mới vào một lớp riêng biệt được gọi là visitor, thay vì cố gắng tích hợp nó vào các lớp hiện có. Đối tượng gốc phải thực hiện hành vi bây giờ được chuyển cho một trong những phương thức của visitor dưới dạng tham số, cung cấp cho phương thức này quyền truy cập vào tất cả dữ liệu cần thiết có trong đối tượng.\n\nBây giờ, điều gì sẽ xảy ra nếu hành vi đó có thể được thực thi trên các đối tượng của các lớp khác nhau? Ví dụ, trong trường hợp này là xuất XML, việc triển khai thực tế có thể sẽ khác một chút trên các lớp nút khác nhau. Do đó, lớp visitor phải xác định không phải một, mà là một tập hợp các phương thức, mỗi phương thức có thể nhận các tham số thuộc các kiểu khác nhau, như thế này:\n\n```c\nclass ExportVisitor implements Visitor is\n    method doForCity(City c) { ... }\n    method doForIndustry(Industry f) { ... }\n    method doForSightSeeing(SightSeeing ss) { ... }\n    // ...\n```\n\nNhưng chính xác thì chúng ta sẽ gọi những phương pháp này như thế nào, đặc biệt là khi xử lý toàn bộ đồ thị? Các phương pháp này có các signature khác nhau, vì vậy ta không thể sử dụng tính đa hình. Để chọn một phương thức visitor thích hợp có thể xử lý một đối tượng nhất định, ta cần kiểm tra lớp của nó.\n\n```c\nforeach (Node node in graph)\n    if (node instanceof City)\n        exportVisitor.doForCity((City) node)\n    if (node instanceof Industry)\n        exportVisitor.doForIndustry((Industry) node)\n    // ...\n}\n```\n\nBạn có thể hỏi, tại sao chúng ta không sử dụng phương thức overloading - nạp chồng? Overloading là khi bạn đặt cùng một tên cho tất cả các phương thức, ngay cả khi chúng có các tham số khác nhau. Thật không may, ngay cả trong trường hợp ngôn ngữ lập trình của ta hỗ trợ overloading (như Java và C #), thì nó cũng không giúp ích được gì cả. Vì lớp chính xác của đối tượng nút không được biết trước, cơ chế overloading sẽ không thể xác định phương thức chính xác để thực thi. Nó sẽ mặc định là phương thức nhận một đối tượng của lớp `Node` cơ sở.\n\nTuy nhiên, pattern visitor giải quyết vấn đề này. Nó sử dụng một kỹ thuật gọi là [**Double Dispatch**](https://refactoring.guru/design-patterns/visitor-double-dispatch), giúp thực thi phương thức thích hợp trên một đối tượng mà không cần các điều kiện rườm rà. \n\nVà thay vì cho phép client chọn một phiên bản thích hợp của phương thức để gọi, tại sao ta không ủy thác lựa chọn này cho các đối tượng mà chúng ta đang chuyển cho visitor làm tham số ? Vì các đối tượng biết các lớp riêng của chúng, chúng có thể chọn một phương pháp thích hợp cho visitor một cách ít lúng túng hơn. Chúng \"accept\" một visitor và cho visitor đó biết phương thức truy cập nào nên được thực thi.\n\n```c\n// Client code\nforeach (Node node in graph)\n    node.accept(exportVisitor)\n\n// City\nclass City is\n    method accept(Visitor v) is\n        v.doForCity(this)\n    // ...\n\n// Industry\nclass Industry is\n    method accept(Visitor v) is\n        v.doForIndustry(this)\n    // ...\n```\n\nRốt cuộc thì ta cũng phải thay đổi các lớp nút. Nhưng ít nhất sự thay đổi là nhỏ và nó cho phép ta thêm các hành vi khác mà không phải thay đổi code một lần nữa.\n\nBây giờ, nếu ta trích xuất một interface chung cho tất cả visitor, thì tất cả các nút hiện có có thể hoạt động với bất kỳ visitor nào mà bạn thêm vào ứng dụng. Nếu bạn thấy mình đang thêm một hành vi mới liên quan đến các nút, tất cả những gì bạn phải làm là triển khai một lớp visitor mới.\n\n## 🚗 Thế Giới Thực\n\n![analogy](./assets/analogy.png)\n\nHãy tưởng tượng một đại lý bảo hiểm dày dạn kinh nghiệm đang mong muốn có được khách hàng mới. Anh ta có thể đến thăm mọi tòa nhà trong khu phố, cố gắng bán bảo hiểm cho mọi người anh ta gặp. Tùy thuộc vào loại hình tổ chức chiếm giữ tòa nhà, anh ta có thể đưa ra các chính sách bảo hiểm chuyên biệt:\n\n- Nếu đó là một tòa nhà dân cư, anh ta bán bảo hiểm y tế.\n- Nếu đó là một ngân hàng, anh ta bán bảo hiểm trộm cắp.\n- Nếu đó là một quán cà phê, anh ấy bán bảo hiểm cháy nổ và thiên tai.\n\n## 🏢 Cấu trúc\n\n![structure](./assets/structure.png)\n\n1. **Visitor** là interface khai báo một tập hợp các phương thức truy cập có thể lấy các concrete element của cấu trúc đối tượng làm tham số. Các phương thức này có thể trùng tên nếu chương trình được viết bằng ngôn ngữ hỗ trợ overloading, nhưng kiểu tham số của chúng phải khác nhau.\n2. **Concrete Visitor** thực hiện một số phiên bản của các hành vi giống nhau, được điều chỉnh cho các lớp concrete element khác nhau.\n3. **Element** là interface khai báo một phương thức để \"accept\" visitor. Phương thức này phải có một tham số được khai báo với kiểu interface visitor. \n4. **Concrete Element** thực hiện phương pháp nghiệm thu. Mục đích của phương thức này là chuyển hướng lệnh gọi đến phương thức của visitor thích hợp tương ứng với lớp element hiện tại. \n\n    Cần biết rằng ngay cả khi một lớp element cơ sở triển khai phương thức này, tất cả các lớp con vẫn phải ghi đè phương thức này trong các lớp của chính chúng và gọi phương thức thích hợp trên đối tượng visitor.\n5. **Client** thường đại diện cho một tập hợp hoặc một số đối tượng phức tạp khác (ví dụ, một cây tổng hợp). Thông thường, client không biết tất cả các lớp concrete element vì chúng làm việc với các đối tượng từ tập hợp đó thông qua một số interface trừu tượng\n\n## 👨‍💻 Mã giả\n\nTrong ví dụ này, Visitor thêm hỗ trợ xuất XML vào hệ thống phân cấp lớp của các hình dạng hình học.\n\n![pseudocode](./assets/pseudocode.png)\n\n*Xuất nhiều loại đối tượng khác nhau sang định dạng XML thông qua đối tượng visitor.*\n\n```c\n// Interface element khai báo phương thức `accept` để\n// nhận interface visitor cơ sở như là tham số.\ninterface Shape is\n    method move(x, y)\n    method draw()\n    method accept(v: Visitor)\n\n\n// Mỗi lớp concrete element phải triển khai phương\n// thức `accept` theo một cách như gọi phương thức\n// của visitor phù hợp với lớp của element.\nclass Dot implements Shape is\n    // ...\n\n\n    // Lưu ý ta gọi `visitDot`, tương ứng với tên lớp hiện \n    // tại. Cách này giúp visitor biết lớp của element\n    // đang làm việc với nó.\n    method accept(v: Visitor) is\n        v.visitDot(this)\n\nclass Circle implements Shape is\n    // ...\n    method accept(v: Visitor) is\n        v.visitCircle(this)\n\nclass Rectangle implements Shape is\n    // ...\n    method accept(v: Visitor) is\n        v.visitRectangle(this)\n\nclass CompoundShape implements Shape is\n    // ...\n    method accept(v: Visitor) is\n        v.visitCompoundShape(this)\n\n\n// Interface visitor khai báo một tập hợp phương thức đi qua\n// tương ứng với các lớp element. Ký hiệu của phương thức\n// đi qua giúp visitior xác định chính xác lớp của element\n// đang xử lý nó.\ninterface Visitor is\n    method visitDot(d: Dot)\n    method visitCircle(c: Circle)\n    method visitRectangle(r: Rectangle)\n    method visitCompoundShape(cs: CompoundShape)\n\n// Concrete visitor triển khai nhiều phiên bản thuật toán\n// giống nhau, thứ làm việc với tất cả lớp concrete element.\n//\n// Bạn có thể có nhiều lợi ích từ làm việc với pattern Visitor\n// khi sử dụng nó với đối tượng có cấu trúc phức tạp như cây\n// Composite. Trong trường hợp này, nó sẽ hữu ích để lưu trữ\n// một vài trạng thái trung gian của thuật toán trong khi thực\n// thi phương thức của visitor qua các đối tượng khác nhau của\n// cấu trúc.\nclass XMLExportVisitor implements Visitor is\n    method visitDot(d: Dot) is\n        // Xuất ID của dấu chấm và hệ toạ độ trung tâm.\n\n    method visitCircle(c: Circle) is\n        // Xuất ID của vòng tròn, toạ độ trung tâm và bán kính.\n\n    method visitRectangle(r: Rectangle) is\n        // Xuất ID của hình chữ nhật, toạ độ trên-trái,\n        // chiều dài và chiều rộng.\n\n    method visitCompoundShape(cs: CompoundShape) is\n        // Xuất ID của hình dạng cũng như danh sách con của ID.\n\n\n\n// Code client chạy thao tác visitor qua bất kỳ tập hợp element\n// mà không cần biết lớp cụ thể của nó. Thao tá accept trực tiếp\n// gọi đến thao tác thích hợp ở đối tượng visitor.\nclass Application is\n    field allShapes: array of Shapes\n\n    method export() is\n        exportVisitor = new XMLExportVisitor()\n\n        foreach (shape in allShapes) do\n            shape.accept(exportVisitor)\n```\n\n## 💡 Ứng dụng\n\n**🐞 Sử dụng Visitor khi bạn cần thực hiện thao tác trên tất cả các phần tử của cấu trúc đối tượng phức tạp (ví dụ: cây đối tượng).**\n\n⚡ Pattern Visitor cho phép bạn thực hiện một thao tác trên một tập hợp các đối tượng có các lớp khác nhau bằng cách để một đối tượng visitor triển khai một số biến thể của cùng một thao tác, tương ứng với tất cả các lớp mục tiêu.\n\n**🐞 Sử dụng Visitor để làm sạch logic nghiệp vụ của các hành vi phụ trợ.**\n\n⚡ Visitor cho phép bạn làm cho các lớp chính của ứng dụng tập trung hơn vào công việc chính của chúng bằng cách trích xuất tất cả các hành vi khác vào một tập hợp các lớp visitor.\n\n**🐞 Sử dụng Visitor khi một hành vi chỉ có ý nghĩa trong một số lớp của hệ thống phân cấp lớp, nhưng không có ý nghĩa trong các lớp khác.**\n\n⚡ Bạn có thể trích xuất hành vi này thành một lớp visitor riêng biệt và chỉ triển khai những phương thức truy cập chấp nhận các đối tượng của các lớp có liên quan, để trống phần còn lại.\n\n## 📋 Triển khai\n\n1. Khai báo interface visitor với một tập hợp các phương thức “ghé thăm”, một phương thức cho mỗi lớp phần tử cụ thể tồn tại trong chương trình.\n\n2. Khai báo interface phần tử. Nếu bạn đang làm việc với hệ thống phân cấp lớp phần tử hiện có, hãy thêm phương thức trừu tượng \"accept\" vào lớp cơ sở của hệ thống phân cấp. Phương thức này phải chấp nhận một đối tượng visitor làm tham số.\n\n3. Thực hiện các phương pháp chấp nhận trong tất cả các lớp phần tử cụ thể. Các phương thức này chỉ phải chuyển hướng cuộc gọi đến một phương thức thăm trên đối tượng visitor đến phù hợp với lớp của phần tử hiện tại.\n\n4. Các lớp phần tử chỉ nên hoạt động với visitor thông qua interface visitor. Tuy nhiên, visitor phải biết tất cả các lớp phần tử cụ thể, được tham chiếu như các kiểu tham số của các phương thức truy cập.\n\n5. Đối với mỗi hành vi không thể được triển khai bên trong phân cấp phần tử, hãy tạo một lớp visitor cụ thể mới và triển khai tất cả các phương pháp truy cập.\n\n    Bạn có thể gặp phải tình huống trong đó visitor sẽ cần quyền truy cập vào một số thành viên riêng tư của lớp phần tử. Trong trường hợp này, bạn có thể đặt các trường hoặc phương thức này ở chế độ công khai, vi phạm tính đóng gói của phần tử hoặc lồng lớp visitor vào lớp phần tử. Điều sau chỉ có thể thực hiện được nếu bạn may mắn làm việc với ngôn ngữ lập trình hỗ trợ các lớp lồng nhau.\n\n6. Client phải tạo các đối tượng visitor và chuyển chúng vào các phần tử thông qua các phương thức \"accept\".\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ *Open/Closed Principle*. Bạn có thể thêm một hành vi mới có thể hoạt động với các đối tượng của các lớp khác nhau mà không cần thay đổi các lớp này.\n\n✔️ *Single Responsibility Principle*. Bạn có thể chuyển nhiều phiên bản của cùng một hành vi vào cùng một lớp.\n\n✔️ Một đối tượng visitor có thể tích lũy một số thông tin hữu ích khi làm việc với nhiều đối tượng khác nhau. Điều này có thể hữu ích khi bạn muốn duyệt qua một số cấu trúc đối tượng phức tạp, chẳng hạn như cây đối tượng và áp dụng visitor vào từng đối tượng của cấu trúc này.\n\n### Nhược điểm\n\n❌ Bạn cần cập nhật tất cả visitor mỗi khi một lớp được thêm vào hoặc xóa khỏi hệ thống phân cấp phần tử.\n\n❌ Visitor có thể thiếu quyền truy cập cần thiết vào các trường riêng tư và phương pháp của các phần tử mà họ phải làm việc với.\n\n## 🔁 Quan hệ với các pattern khác\n\nBạn có thể coi **Visitor** như một phiên bản mạnh mẽ của **Command**. Các đối tượng của nó có thể thực thi các hoạt động trên các đối tượng khác nhau của các lớp khác nhau.\n\nBạn có thể sử dụng **Visitor** cùng với **Iterator** để duyệt qua một cấu trúc dữ liệu phức tạp và thực hiện một số thao tác trên các phần tử của nó, ngay cả khi tất cả chúng đều có các lớp khác nhau\n\nBạn có thể sử dụng **Visitor** để thực hiện một thao tác trên toàn bộ cây **Composite**.\n\n# Nguồn\n\n[**refactoring**](https://refactoring.guru/design-patterns/template-method)"
  },
  {
    "path": "creational-pattern/README.md",
    "content": "# Creational Design Patterns\n\nCreational pattern cung cấp các cơ chế tạo đối tượng khác nhau, giúp tăng tính linh hoạt và tái sử dụng code hiện có.\n\n## Factory Method\n\n[![factory-method-mini](./assets/factory-method-mini.png)](./factory-method)\n\nCung cấp một interface cho tạo đối tượng ở lớp cha, nhưng cho phép lớp con thay đổi kiểu đối tượng sẽ được tạo.\n\n## Abstract Factory\n\n[![abstract-factory-mini](./assets/abstract-factory-mini.png)](./abstract-factory)\n\nGiúp bạn tạo các đối tượng có liên quan với nhau trong một nhóm mà không cần chỉ định đến lớp cụ thể của chúng.\n\n## Builder\n\n[![builder-mini](./assets/builder-mini.png)](./builder)\n\nXây dựng các đối tượng phức tạp từng bước một. Pattern này cho phép bạn tạo và biểu diễn các kiểu đối tượng khác nhau bằng code khởi tạo giống nhau.\n\n## Prototype\n\n[![prototype-mini](./assets/prototype-mini.png)](./prototype)\n\nGiúp bạn sao chép một đối tượng mà code của bạn sẽ không phụ thuộc vào lớp của đối tượng đó.\n\n## Singleton\n\n[![singleton-mini](./assets/singleton-mini.png)](./singleton)\n\nĐảm bảo ràng một lớp chỉ với một thực thể duy nhất, trong khi cung cấp điểm truy cập toàn cục cho thực thể đấy."
  },
  {
    "path": "creational-pattern/abstract-factory/README.md",
    "content": "# Abstract Factory\n\n## 📜 Mục đích\n\n**Abstract Factory** là một design pattern thuộc nhóm creational, dùng để tạo ra các đối tượng có quan hệ gần gũi với nhau mà không cần chỉ định đến lớp cụ thể của chúng.\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nGiả sử bạn đang tạo một trang bán đồ nội thất. Code của bạn bao gồm các lớp sau:\n1. Các sản phẩm có quan hệ với nhau như: `Sofa`, `Chair` và `CoffeTable`.\n2. Các biến thể của nhóm sản phẩm đó. Ví dụ như nhóm `Sofa` + `Chair` + `CoffeTable` có các biến thể như `Modern`, `Victorian` và `ArtDeco`.\n\n![problem](./assets/problem.png)\n\nBạn cần có cách để khi tạo một đồ nội thất đơn lẻ, nó phải phù hợp với các đồ vật khác trong nhóm của nó. Khách hàng sẽ khó chịu khi họ nhận về những đồ vật trong nhóm có biến thể khác nhau.\n\n![problem1](./assets/problem1.png)\n\nBên cạnh đó, bạn không muốn thay đổi code mỗi khi thêm sản phẩm hoặc nhóm sản phẩm trong chương trình. Danh mục nội thất được cập nhật rất thường xuyên, và bạn không muốn thay đổi code mỗi khi nó diễn ra.\n\n## 😊 Giải pháp\n\nViệc đầu tiên cần làm theo Abstract Factory là khai báo inteface rõ ràng cho mỗi sản phẩm riêng biệt trong nhóm sản phẩm. Và tạo tất cả biến thể của sản phẩm theo sau inteface đó. Ví dụ tất cả biến thể của ghế được triển khai trong interface `Chair`, tất cả sofa được triển khai trong interface `Sofa` ,...\n\n![solution1](./assets/solution1.png)\n\nBước tiếp theo là khai báo *Abstract Factory* - là interface chứa tất cả phương thức tạo cho tất cả sản phẩm trong nhóm sản phẩm (vd: `createChair`, `createSofa` và `createCoffeTable`). Các phương thức này trả về một kiểu sản phẩm **trừu tượng (abstract)** được biểu diễn bởi interface mà chúng ta trích xuất trước đó: `Chair`, `Sofa`, `CoffeTable`,...\n\n![solution2](./assets/solution2.png)\n\nVậy còn các biến thể của sản phẩm? Với từng biến thể của nhóm sản phẩm, ta tạo ra một lớp factory riêng biệt dựa trên interface **Abstract Factory**. Factory là lớp trả về kiểu sản phẩm riêng biệt. Ví dụ, `ModernFurnitureFactory` có thể tạo ra các đối tượng `ModernChair`, `ModernSofa` hay `ModernCoffeTable`.\n\nCode client làm việc với factory hay sản phẩm thông qua interface trừu tượng. Thế nên bạn có thể thay đổi kiểu factory hay biến thể của sản phẩm cho code client nhận mà không gây ra bất kỳ lỗi gì.\n\n![solution3](./assets/solution3.png)\n\nGiả sử client muốn một factory để tạo ghế (chair). Nó sẽ không cần quan tâm kiểu của lớp factory đó, cũng như kiểu ghế nhận về. Dù là Modern hay Victorian, nó cũng sẽ xử lý theo cùng một cách là thông qua interface trừu tượng `Chair`. Với cách tiếp cận này client chỉ cần quan tâm là ghế sẽ triển khai phương thức `sitOn` như thế nào. Bên cạnh đó, bất kỳ biến thể nào của `chair`, nó cũng sẽ phù hợp với `sofa` và `coffe-table` được tạo cùng đối tượng factory.\n\nNếu bạn thắc mắc: client chỉ làm việc với interface trừu tượng, vậy thì cái gì sẽ tạo ra factory ?. Thông thường ứng dụng sẽ tạo đối tượng factory cụ thể ở giai đoạn khởi tạo, nhưng trước đó ứng dụng sẽ tạo factory dựa trên kiểu cấu hình hoặc thiết lập môi trường.\n\n## 🏢 Cấu trúc\n\n![structure](./assets/structure.png)\n\n1. **Abstract Product** là inteface cho các sản phẩm riêng biệt nhưng có quan hệ với nhau tạo nên một nhóm sản phẩm.\n2. **Concrete Product** là các triển khai biến thể của abstract product, được gom nhóm theo biến thể. Mỗi abstract product (chair/sofa) sẽ được triển khai tất cả biến thể (modern, victorian).\n3. **Abstract Factory** là interface có tập hợp phương thức khởi tạo cho từng abstract product.\n4. **Concrete Factory** là triển khai phương thức khởi tạo của abstract factory. Mỗi concrete factory tương ứng với biến thể cụ thể của sản phẩm và chỉ tạo sản phẩm theo biến thể đó.\n5. Mặc dù concrete factory tạo ra các concrete product, nhưng signature của phương thức khởi tạo trả về sẽ tương ứng với abstract product. Với cách này code client sử dụng factory sẽ không cần quan tâm tới biến thể cụ thể của sản phẩm từ factory. Nó có thể làm việc với bất kỳ biến thể nào miễn là giao tiếp với các đối tượng thông qua interface trừu tượng.\n\n## 👨‍💻 Mã giả\n\nVí dụ này minh hoạ cách Abstract Factory có thể sử dụng để tạo các phần tử UI đa nền tảng mà không cần ghép code client với lớp UI cụ thể, đồng thời giữ cho tất cả các phần tử được tạo nhất quán với hệ điều hành đã chọn\n\n![pseudocode](./assets/pseudocode.png)\n\nCác phần tử UI trên các ứng dụng đa nền tảng sẽ được triển khai giống nhau, sẽ có một chút khác biệt trên các hệ điều hành khác nhau. Hơn nữa, nhiệm vụ của bạn là đảm bảo style của các phần tử UI phù hợp với hệ điều hành hiện tại. Bạn sẽ không muốn chương trình hiển thị MacOS control khi được thực thi trên Windows.\n\nAbstract Factory sẽ khai báo tập hợp các phương thức khởi tạo mà code client có thể dùng để tạo các kiểu phần tử UI khác nhau. Concrete factory tương ứng với hệ điều hành cụ thể sẽ tạo ra các phần tử UI phù hợp với hệ điều hành đó.\n\nNó hoạt động như sau: khi ứng dụng bắt đầu chạy, nó sẽ kiểm tra loại hệ điều hành hiện tại. Ứng dụng sẽ dùng thông tin đó để tạo ra một đối tượng factory từ lớp tương ứng với hệ điều hành. Các phần còn lại sẽ dùng factory để tạo ra phần tử UI. Điều này ngăn việc tạo các phần tử UI sai lệch.\n\nVới cách tiếp cận này, code client không phụ thuộc lớp cụ thể của factory hay phần tử UI, miễn là nó làm việc với các đối tượng thông qua abstract factory. Không những thế, code client còn hỗ trợ các factory khác và phần tử UI bạn thêm vào trong tương lai.\n\nNhư vậy bạn không cần chỉnh sửa code client mỗi lần thêm biến thể của phần tử UI trong ứng dụng. Bạn chỉ cần tạo một lớp factory mới tạo ra các phần tử này và sửa đổi một chút code khởi tạo để ứng dụng chọn lớp đó khi thích hợp.\n\n```c\n// Interface Abstract Factory khai bao tập hợp phương thức\n// trả về kiểu abstract product khác nhau. Các sản phẩm chung\n// nhóm có quan hệ với nhau về chủ đề hoặc một khái niệm cấp cao.\n// Sản phẩm từ một nhóm thường có thể cộng tác với nhau. Nhóm \n// sản phẩm thường có một hay nhiều biến thể, nhưng sản phẩm của\n// một biến thể này sẽ không tương thích với biến thể khác.\ninterface GUIFactory is\n    method createButton():Button\n    method createCheckbox():Checkbox\n\n\n// Concrete factory tạo ra nhóm sản phẩm thuộc về một biến thể.\n// Factory đảm bảo rằng sản phẩm tạo ra luôn tương thích.\n// Signature của phương thức concrete factory trả về \n// abstract product, trong khi bên trong phương thức,\n// concrete product được tạo ra.\nclass WinFactory implements GUIFactory is\n    method createButton():Button is\n        return new WinButton()\n    method createCheckbox():Checkbox is\n        return new WinCheckbox()\n\n// Mỗi concrete factory có một biến thể sản phẩm tương ứng.\nclass MacFactory implements GUIFactory is\n    method createButton():Button is\n        return new MacButton()\n    method createCheckbox():Checkbox is\n        return new MacCheckbox()\n\n\n// Mỗi sản phẩm riêng biệt của nhóm sản phẩm nên có một interface\n// cơ sở. Tất cả biết thể của sản phẩm sẽ được triển khai từ \n// interface này\ninterface Button is\n    method paint()\n\n\n// Concrete product được tạo bởi concrete factory tương ứng.\nclass WinButton implements Button is\n    method paint() is\n        // Hiển thị button trong Windows\n\nclass MacButton implements Button is\n    method paint() is\n        // Hiển thị button trong MacOS\n\n// Đây là interface cơ sở của một sản phẩm khác. Tất cả \n// sản phẩm có thể tương tác với nhau, nhưng tương tác\n// chỉ khả dụng giữa hai sản phẩm cùng một biến thể.\ninterface Checkbox is\n    method paint()\n\nclass WinCheckbox implements Checkbox is\n    method paint() is\n        // Hiển thị checkbox trong Windows\n\nclass MacCheckbox implements Checkbox is\n    method paint() is\n        // Hiển thị checkbox trong MacOS\n\n\n// Code client làm việc với factory và sản phẩm chỉ thông qua\n// kiểu trừu tượng: GUIFactory, Button và Checkbox. Nó giúp bạn\n// chuyển bất kỳ lớp con nào của factory sang code client mà\n// không làm hỏng nó.\nclass Application is\n    private field factory: GUIFactory\n    private field button: Button\n    constructor Application(factory: GUIFactory) is\n        this.factory = factory\n    method createUI() is\n        this.button = factory.createButton()\n    method paint() is\n        button.paint()\n\n\n// Ứng dụng chọn kiểu factory tùy thuộc vào cấu hình hiện tại \n// hoặc thiết lập môi trường và tạo nó trong thời gian chạy\n// (thường ở giai đoạn khởi tạo).\nclass ApplicationConfigurator is\n    method main() is\n        config = readApplicationConfigFile()\n\n        if (config.OS == \"Windows\") then\n            factory = new WinFactory()\n        else if (config.OS == \"Mac\") then\n            factory = new MacFactory()\n        else\n            throw new Exception(\"Error! Unknown operating system.\")\n\n        Application app = new Application(factory)\n```\n\n## 💡 Ứng dụng\n\n**🐞 Sử dụng Abstract Factory khi bạn cần làm việc với nhiều biến thể của một nhóm sản phẩm, mà bạn không muốn phụ thuộc vào lớp cụ thể của sản phẩm đó - chúng có thể chưa biết trước hoặc đơn giản là bạn muốn mở rộng trong tương lai.**\n\n⚡  Abstract Factory cung cấp cho bạn interface để tạo các đối tượng từ mỗi lớp trong nhóm sản phẩm miễn là code của bạn tạo đối tượng thông qua interface, bạn sẽ không phải lo lắng các vấn đề tạo sai biến thể của sản phẩm hay không phù hợp với sản phẩm đã tạo trong ứng dụng.\n\n- Khi triển khai Abstract Factory cần lưu ý nến bạn có một lớp với một tập hợp phương thức Factory, nó có thể làm mờ nhiệm vụ chính của Abstract.\n- Một thiết kế chương trình tốt là khi *mỗi lớp sẽ chỉ làm một nhiệm vụ*. Khi một lớp xử lý nhiều loại sản phẩm, bạn có thể trích xuất các phương thức factory của nó thành một lớp factory độc lập hoặc triển khai Abstract Factory toàn diện.\n\n## 📋 Triển khai\n\n1. Lập sơ đồ ma trận cho các loại sản phẩm riêng biệt so với các biến thể của chúng.\n\n2. Khai báo interface, Abstract Product cho tất cả loại sản phẩm. Sau đó tạo ra lớp concrete product triển khai interface này.\n\n3. Khai báo interface, Abstract Factory với tập hợp phương thức khởi tạo cho tất cả abstract product.\n\n4. Triển khai các lớp concrete factory cho từng loại biến thể của sản phẩm\n\n5. Tạo code khởi tạo factory đâu đó trong ứng dụng. Nó sẽ khởi tạo một trong các lớp concrete factory, dựa trên cấu hình ứng dụng hoặc thiết lập môi trường. Truyền đối tượng factory này cho tất cả lớp tạo sản phẩm.\n\n6. Kiểm tra code và tìm tất cả các lệnh gọi trực tiếp đến constructor của sản phẩm. Thay thế chúng bằng các lệnh gọi đến phương thức tạo thích hợp trên đối tượng factory.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ Bạn có thể chắc chắn rằng các sản phẩm lấy từ một factory sẽ tương thích với nhau.\n\n✔️ Tránh được kết hợp quá chặt chẽ giữa code client và concrete product.\n\n✔️ *Single Responsibility Principle*. Bạn có thể di chuyển code tạo sản phẩm vào một nơi trong chương trình, giúp hỗ trợ code dễ dàng hơn.\n\n✔️ *Open/Closed Principle*. Bạn có thể thêm các biến thể mới vào chương trình, mà không làm ảnh hưởng đến code client hiện tại.\n\n### Nhược điểm\n\n❌ Code có thể trở nên phức tạp khi bạn thêm vào quá nhiều interface và lớp để triển khai pattern.\n\n## 🔁 Quan hệ với các pattern khác\n\nNhiều pattern bắt đầu bằng cách sử dụng **Factory Method** (ít phức tạp hơn và có thể tùy chỉnh nhiều hơn thông qua các lớp con) và phát triển theo hướng **Abstract Factory**, **Prototype** hoặc **Builder** (linh hoạt hơn nhưng phức tạp hơn).\n\nCác lớp **Abstract Factory** thường dựa trên một tập hợp các **Factory Method**, nhưng bạn cũng có thể sử dụng **Prototype** để cấu trúc các phương thức trên các lớp này.\n\n**Builder** tập trung vào việc xây dựng các đối tượng phức tạp theo từng bước. **Abstract Factory** chuyên tạo các nhóm đối tượng. **Abstract Factory** trả lại sản phẩm ngay lập tức, trong khi **Builder** cho phép bạn chạy một số bước xây dựng bổ sung trước khi tìm nạp sản phẩm.\n\n**Abstract Factory** có thể dùng như một giải pháp thay thế cho **Facade** khi bạn chỉ muốn ẩn cách các đối tượng hệ thống con được tạo ra khỏi code client.\n\nBạn có thể sử dụng **Abstract Factory** cùng với **Bridge**. Việc ghép nối này rất hữu ích khi một số abstract được xác định bởi **Bridge** chỉ có thể hoạt động với các triển khai cụ thể. Trong trường hợp này, **Abstract Factory** có thể đóng gói các quan hệ này và ẩn sự phức tạp khỏi code client.\n\nTất cả các **Abstract Factory**, **Builder** và **Prototype** đều có thể được triển khai dưới dạng các **Singleton**.\n\n# Nguồn\n\n[**refactoring**](https://refactoring.guru/design-patterns/abstract-factory)"
  },
  {
    "path": "creational-pattern/builder/README.md",
    "content": "# Builder\n\n## 📜 Mục đích\n\n**Builder** là design pattern thuộc nhóm creational, giúp bạn khởi tạo những đối tượng phức tạp theo từng bước. Pattern này cho phép bạn tạo và biểu diễn các kiểu đối tượng khác nhau bằng code khởi tạo giống nhau.\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nHãy tưởng tượng một đối tượng phức tạp đòi hỏi nhiều công sức, phải tạo từng bước một với rất nhiều trường và các đối tượng lồng nhau. Các đoạn code khởi tạo như vậy sẽ nằm rất sâu trong hàm khởi tạo (constructor) khổng lồ với rất nhiều tham số. Hoặc tệ hơn là nó nằm rải rác trên các đoạn code client.\n\n![problem1](./assets/problem1.png)\n\nVí dụ như làm thế nào để tạo một đối tượng `House`. Để xây dựng một ngôi nhà đơn giản, bạn cần tạo bốn bức tường, nền móng, cửa lớn, các cửa sổ phù hợp và mái nhà. Nhưng nếu sau này, bạn cần mở rộng nhà to hơn, sáng sủa hơn, với sân sau và những hệ thống tiên tiến như (hệ thống ống nước, hệ thống sưởi ấm, hệ thống dây điện)?\n\nGiải pháp đơn giản nhất là mở rộng lớp cơ sở `House`, và tạo ra tập hợp lớp con để kết hợp tất cả các tham số. Nhưng điều này sẽ khiến bạn tạo ra một số lượng đáng kể lớp con, đồng thời với bất kỳ tham số mới nào, ví dụ như kiểu hiên nhà sẽ yêu cầu phát triển hệ phân cấp lớp nhiều hơn nữa.\n\nLúc này cách tiếp cận khác tránh việc tạo nhiều lớp con. Là bạn có thể tạo một hàm khởi tạo (constructor) lớn trong lớp cơ sở `House` với tất cả tham số cần thiết để điều khiển đối tượng `House`. Cách này tuy có thể giải quyết vấn đề lớp con nhưng lại rơi vào vấn đề khác.\n\n![problem2](./assets/problem2.png)\n\n*Nhược điểm của constructor nhiều tham số là không phải lúc nào cũng cần đến các tham số*\n\nTrong phần lớn trường hợp, các tham số của bạn sẽ không được dùng đến, điều này làm cho *hàm khởi tạo của bạn rất tệ*. Ví dụ chỉ một phần trong nhà bạn có hồ bơi, thì những tham số liên quan đến hồ bơi sẽ vô dụng khoảng 90%.\n\n## 😊 Giải pháp\n\nÝ tưởng của Builder pattern là bạn sẽ trích xuất các đoạn code khởi tạo đối tượng ra khỏi lớp của nó và chuyển đến một đối tượng riêng biệt gọi là *builder*.\n\n![solution1](./assets/solution1.png)\n\n*Builder pattern giúp bạn khởi tạo đối tượng phức tạp theo từng bước.*\n\nPattern khởi tạo đối tượng theo trật tự từng bước một (vd như `buildWalls`, `buildDoor`,...).\nĐể tạo đối tượng, bạn thực thi một loạt các bước này trên đối tượng builder. Nhưng bạn không cần phải gọi đến tất các bước, mà chỉ cần gọi đến bước cần thiết để tạo cấu hình cụ thể của đối tượng.\n\nMột vài bước khởi tạo yêu cầu triển khai khác nhau, khi bạn cần biểu diễn các biến thể của sản phẩm. Ví dụ: tường của một cabin sẽ được xây bằng gỗ, còn tường của một lâu đài sẽ được xây bằng đá.\n\nTrong trường hợp đấy, ta cần tạo ra nhiều lớp builder khác nhau, để triển khai các bước xây dựng giống nhau nhưng khác về cách thức. Sau đó bạn sử dụng builder trong quá trình khởi tạo để tạo ta các kiểu đối tượng khác nhau.\n\n![solution2](./assets/solution2.png)\n\nVí dụ, cần xây dựng 3 ngôi nhà, cái thứ nhất được xây từ gỗ và kính, cái thứ hai được xây từ đá và sắt còn cái thứ ba được xây từ vàng và kim cương. Như vậy với lệnh gọi các bước thực hiện như nhau, ta sẽ có một ngôi nhà thông thường, một lâu đài và một cung điện. Tuy các nhiệm vụ giống nhau nhưng các xây dựng khác nhau với từng biến thể.\n\nSong điều này chỉ hoạt động khi code client gọi các lệnh khởi tạo tương tác với builder thông qua inteface chung.\n\n### Director\n\nBạn có thể trích xuất một loạt lệnh gọi đến các bước của hàm khởi tạo, mà bạn sử dụng để xây dựng sản phẩm thành một lớp riêng biệt có tên là *director*.\n\nLớp director xác định thứ tự thực thi của các bước xây dựng, trong khi builder cung cấp việc triển khai cho các bước đó.\n\n![directory](./assets/directory.png)\n\nCác lớp director là không bắt buộc. Bạn có thể gọi các bước xây dựng theo thứ tự cụ thể trực tiếp từ code client. Tuy nhiên, lớp director là nơi lý tưởng để đặt các quy trình khởi tạo khác nhau mà bạn có thể sử dụng lại trong chương trình của mình.\n\nNgoài ra, lớp director sẽ ẩn hoàn toàn chi tiết khởi tạo của sản phẩm với code client. Code client chỉ cần liên kết với director, rồi nhận hàm khởi tạo từ director và kết quả từ builder.\n\n## 🏢 Cấu trúc\n\n![structure](./assets/structure.png)\n\n1. **Builder** là interface khai báo các bước tạo sản phẩm chung cho tất cả loại builder.\n2. **Concrete Builder** cung cấp các triển khai khác nhau cho các bước khởi tạo. Concrete Builder có thể tạo sản phẩm mà không cần theo interface chung.\n3. **Product** là đối tượng kết quả. Product được tạo bởi nhiều builder khác nhau không nhất thiết phải thuộc cùng một lớp phân cấp hay interface chung.\n4. **Director** lớp định nghĩa thứ tự gọi các bước khởi tạo. Vì vậy bạn có thể tạo và sử dụng cho cấu hình cụ thể của sản phẩm.\n5. **Client** phải liên kết đến một trong các đối tượng builder và director. Thường chỉ được thực hiện một lần, thông qua tham số của hàm khởi tạo director. Sau đó director sẽ sử dụng đối tượng builder cho tất cả khởi tạo tiếp theo. Tuy nhiên có một giải pháp thay thế là khi client truyền đối tượng builder sang phương thức production trong director. Trong trường hợp này, bạn có thể sử dụng builder khác nhau mỗi khi cần tạo thứ gì đó với director.\n\n## 👨‍💻 Mã giả\n\nĐây là ví dụ minh hoạ cách pattern **Builder** sử dụng lại code tạo đối tượng khi xây dựng các kiểu sản phẩm khác nhau, ví dụ như xe hơi và tạo các hướng dẫn sử dụng tương ứng.\n\n![pseudocode](./assets/pseudocode.png)\n\nXe hơi là một đối tượng phức tạp có thể được tạo bằng hàng trăm cách khác nhau. Thay vì một lớp `Car` với hàm khởi tạo (constructor) khổng lồ, ta sẽ trích xuất code lắp ráp xe vào một lớp `CarBuilder` riêng biệt. Lớp này sẽ có tập hợp các phương pháp cấu hình cho từng bộ phận trong xe.\n\nNếu code client cần lắp ráp xe theo một mô hình đặc biệt, được tinh chỉnh thì nó có thể làm việc trực tiếp với builder. Trong trường hợp khác, nó có thể uỷ thác việc lắp ráp cho lớp director, nơi biết cách sử dụng builder để tạo ra những mẫu xe thời thượng nhất.\n\nBạn có thể bị sốc nếu biết mọi chiếc xe đều có hướng dẫn sử dụng (hầu hết mọi người không đọc chúng :v). Hướng dẫn sử dụng là thứ mô tả mọi tính năng của chiếc xe đấy, vì vậy với các mẫu xe khác nhau sẽ có hướng dẫn sử dụng khác nhau. Đó là lý do bạn nên sử dụng cùng quy trình tạo cho chiếc xe và hướng dẫn sử dụng của nó. Dĩ nhiên, tạo hướng dẫn sử dụng không giống tạo một chiếc xe, đó là lý do ta cung cấp cho nó một lớp builder khác chuyên biệt cho việc tạo hướng dẫn sử dụng. Lớp này thực hiện các phương thức xây dựng tương tự như `CarBuilder`, nhưng thay vì chế tạo các bộ phận, nó chỉ mô tả chúng. Bằng cách truyền các builder vào cùng một đối tượng director, ta có thể tạo ra chiếc xe hay hướng dẫn sử dụng của nó.\n\nCuối cùng là tìm nạp đối tượng kết quả. Một chiếc xe bằng kim loại và hướng dẫn sử dụng bằng giấy dù có quan hệ những vẫn rất khác nhau. Nên ta không thể đặt phương thức nạp kết quả trong director, vì nó không kết hợp với lớp product cụ thể. Do đó ta sẽ nhận về kết quả tạo từ builder.\n\n```c\n// Sử dụng pattern Builder có ý nghĩa khi sản phẩm\n// quá phức tạp và yêu cầu nhiều cấu hình mở rộng. \n// Hai sản phẩm có quan hệ với nhau, dù không có\n// interface chung.\n\nclass Car is\n    // Xe hơi có thể có GPS, hộp đen và một số ghế ngồi.\n    // Cái mẫu xe khác nhau(xe thể thao, SUV, xe mui trần)\n    // sẽ có tính năng được thiết lập khác nhau.\n\nclass Manual is\n    // Mỗi xe sẽ có một hướng dẫn sử dụng cho người dùng\n    // tương ứng với cấu hình xe đó để mô tả mọi tính năng.\n\n\n// Interface builder chỉ định phương thức cụ thể để tạo\n// các phần khác nhau trong đối tượng sản phẩm.\ninterface Builder is\n    method reset()\n    method setSeats(...)\n    method setEngine(...)\n    method setTripComputer(...)\n    method setGPS(...)\n\n\n// Lớp concrete builder theo sau interface builder và cung cấp\n// các triển khai cụ thể cho bước xây dựng. Chương trình của bạn \n// sẽ có nhiều biến thể builder cho các triển khai khác nhau.\nclass CarBuilder implements Builder is\n    private field car:Car\n\n    // Một fresh builder nên bao gồm đối tượng sản phẩm trống\n    // để sử dụng cho các lắp ráp trong tương lai.\n    constructor CarBuilder() is\n        this.reset()\n\n    // Phương thức reset xoá đối tượng được xây dựng.\n    method reset() is\n        this.car = new Car()\n\n    // Tất cả các bước tạo làm việc với cùng một đối tượng sản phẩm.\n    method setSeats(...) is\n        // Thiết lập số ghế ngồi trong xe.\n\n    method setEngine(...) is\n        // Cài đặt bộ động cơ.\n\n    method setTripComputer(...) is\n        // Cài đặt máy tính hành trình.\n\n    method setGPS(...) is\n        // Cài đặt GPS.\n    \n    // Concrete builder phải cung cấp phương thức của nó để\n    // truy xuất kết quả. Các kiểu builder khác nhau sẽ tạo \n    // ra sản phẩm hoàn chỉnh khác nhau mà không cần theo một\n    // interface chung. Do đó, phương thức này không thể khai \n    // báo ở interface builder (chí ít là với các ngôn ngữ lập\n    // trình tĩnh.)\n    //\n    // Thông thường, sau khi nhận kết quả cuối cùng từ client,\n    // builder sẽ sẵn sàng cho việc tạo ra một sản phẩm khác.\n    // Đó là lý do ta đặt lệnh gọi phương thức reset ngay phía\n    // sau phương thức `getProduct`. Tuy nhiên, điều này là không\n    // bắt buộc, bạn có thể để cho builder đợi đến lệnh gọi reset\n    // từ code client trước khi loại bỏ kết quả trước đó.\n    method getProduct():Car is\n        product = this.car\n        this.reset()\n        return product\n\n// Không giống creational pattern khác, builder giúp bạn\n// tạo sản phẩm không cần theo interface chung.\nclass CarManualBuilder implements Builder is\n    private field manual:Manual\n\n    constructor CarManualBuilder() is\n        this.reset()\n\n    method reset() is\n        this.manual = new Manual()\n\n    method setSeats(...) is\n        // Tài liệu số ghế của xe.\n\n    method setEngine(...) is\n        // Thêm hướng dẫn động cơ.\n\n    method setTripComputer(...) is\n        // Thêm hướng dẫn máy tính hành trình.\n\n    method setGPS(...) is\n        // Thêm hướng dẫn GPS.\n\n    method getProduct():Manual is\n        // Trả về hướng dẫn sử dụng và reset builder\n\n\n// Director chỉ chịu trách nhiệm cho thực thi các bước xây dựng\n// theo một thứ tự cụ thể. Nó hữu ích khi tạo sản phẩm theo một\n// trật tự xác định hoặc một cấu hình rõ ràng.\n// Nói đúng hơn, lớp director là tuỳ chọn, để client có thể gián\n// tiếp điều khiển builder.\nclass Director is\n    private field builder:Builder\n\n    // Director làm việc với bất kỳ builder nào mà code client\n    // truyền vào nó. Với cách này, code client có thể thay đổi\n    // kiểu cuối cùng của sản phẩm vừa được lắp ráp.\n    method setBuilder(builder:Builder)\n        this.builder = builder\n\n    // Director có thể tạo nhiều biến thể sản phẩm\n    // với cùng các bước xây dựng.\n    method constructSportsCar(builder: Builder) is\n        builder.reset()\n        builder.setSeats(2)\n        builder.setEngine(new SportEngine())\n        builder.setTripComputer(true)\n        builder.setGPS(true)\n\n    method constructSUV(builder: Builder) is\n        // ...\n\n\n// Code client tạo đối tượng builder, truyền nó vào director \n// sau đó bắt đầu quá trình khởi tạo. Kết quả cuối cùng được\n// truy xuất từ đối tượng builder.\nclass Application is\n\n    method makeCar() is\n        director = new Director()\n\n        CarBuilder builder = new CarBuilder()\n        director.constructSportsCar(builder)\n        Car car = builder.getProduct()\n\n        CarManualBuilder builder = new CarManualBuilder()\n        director.constructSportsCar(builder)\n\n\n        // Sản phẩm cuối cùng thường được truy xuất từ đối\n        // tượng builder vì director không nhận biết được\n        // concreate builder và sản phẩm.\n        Manual manual = builder.getProduct()\n```\n\n## 💡 Ứng dụng\n\n**🐞 Sử dụng Builder để loại bỏ các \"hàm khởi tạo khổng lồ\"** \n\n⚡  Giả sử bạn có một phương thức khởi tạo với 10 tham số. Gọi một con \"quái vật\" như vậy là rất bất tiện, nên bạn đã overload constructor để tạo ra nhiều phiên bản ít tham số hơn. Các constructor này vẫn tham chiếu đến cái chính, và truyền một số giá trị mặc định vào bất kỳ tham số nào bị bỏ qua.\n\n```\nclass Pizza {\n    Pizza(int size) { ... }\n    Pizza(int size, boolean cheese) { ... }\n    Pizza(int size, boolean cheese, boolean pepperoni) { ... }\n    // ...\n```\n\nBuilder cho phép bạn xây dựng đối tượng từng bước, chỉ dùng những bước bạn thực sự cần. Sau khi triển khai pattern bạn không cần nhồi nhét hàng tá tham số vào constructor.\n\n**🐞 Sử dụng Builder khi bạn muốn code của bạn tạo ra các sản phẩm có biểu diễn khác nhau (như nhà tường và nhà gỗ)**\n\n⚡  Builder pattern có thể áp dụng khi tạo các biểu diễn khác nhau của sản phẩm gồm các bước tương tự nhau chỉ khác về chi tiết.\n\n**🐞 Sử dụng Builder để tạo ra những cây Composite và các đối tượng phức tạp khác**\n\n⚡  Builder tạo sản phẩm theo từng bước một. Bạn có thể trì hoãn việc thực thi một số bước mà không làm ảnh hưởng đến sản phẩm cuối cùng. Bạn cũng có thể gọi đệ quy, điều này rất hữu ích khi bạn xây dựng đối tượng cây. Builder không để lộ sản phẩm khi đang thực hiện các bước tạo. Điều này tránh việc code client tìm nạp sản phẩm chưa hoàn chỉnh.\n\n## 📋 Triển khai\n\n1. Đảm bảo bạn đã xác định rõ ràng các bước khởi tạo để xây dựng tất cả sản phẩm khả dụng. Nếu không bạn không thể triển khai pattern này.\n\n2. Khai báo các bước trong interface cơ sở Builder.\n\n3. Tạo lớp concrete builder cho từng biểu diễn sản phẩm và triển khai các bước khởi tạo của chúng. Đừng quên rằng việc triển khai phương thức để tìm nạp kết quả cho khởi tạo. Đó là lý do phương thức này không thể đặt trong interface Builder, vì các builder khác nhau có thể tạo ra các sản phẩm không cùng interface. Do đó bạn không biết kiểu trả về của phương thức. Tuy nhiên, nếu bạn đang xử lý các sản phẩm từ một hệ thống phân cấp, thì phương pháp tìm nạp có thể được thêm vào interface cơ sở một cách an toàn.\n\n4. Tạo lớp director. Nó bao gồm nhiều cách khác nhau để tạo sản phẩm trên cùng một đối tượng builder.\n\n5. Code client tạo ra cả đối tượng builder và director. Trước khi bắt đầu khởi tạo, client truyền đối tượng builder vào director, thông thường client chỉ làm một lần thông qua tham số của hàm khởi tạo director. Director sử dụng builder cho tất cả khởi tạo trong tương lai. Có một cách tiếp cận khác là builder chuyển trực tiếp đến phương thức constructor của director.\n\n6. Chỉ có thể nhận kết quả trực tiếp từ director nếu tất cả sản phẩm cùng theo một interface chung. Ngược lại thì phải nhận từ builder.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ Bạn có thể tạo đối tượng từng bước, bỏ qua vài bước hay chạy đệ quy.\n\n✔️ Bạn có thể sử dụng lại code khởi tạo cho xây dựng sản phẩm có biểu diễn khác nhau.\n\n✔️ *Single Responsibility Principle*. Bạn có thể tách code khởi tạo phức tạp khỏi logic nghiệp vụ của sản phẩm\n\n### Nhược điểm\n\n❌ Độ phức tạp tổng thể của code tăng lên vì pattern yêu cầu tạo nhiều lớp mới.\n\n## 🔁 Quan hệ với các pattern khác\n\nNhiều pattern bắt đầu bằng cách sử dụng **Factory Method** (ít phức tạp hơn và có thể tùy chỉnh nhiều hơn thông qua các lớp con) và phát triển theo hướng **Abstract Factory**, **Prototype** hoặc **Builder** (linh hoạt hơn nhưng phức tạp hơn).\n\n**Builder** tập trung vào việc xây dựng các đối tượng phức tạp theo từng bước. **Abstract Factory** chuyên tạo các nhóm đối tượng. **Abstract Factory** trả lại sản phẩm ngay lập tức, trong khi **Builder** cho phép bạn chạy một số bước xây dựng bổ sung trước khi tìm nạp sản phẩm.\n\nBạn có thể sử dụng **Builder** khi tạo các cây **Composite** phức tạp vì bạn có thể lập trình các bước xây dựng của nó để hoạt động một cách đệ quy.\n\nBạn có thể kết hợp **Builder** với **Bridge**: lớp director đóng vai trò abstract, trong khi các builder khác đóng vai trò implementation.\n\nTất cả các **Abstract Factory**, **Builder** và **Prototype** đều có thể được triển khai dưới dạng các **Singleton**.\n\n\n# Nguồn\n\n[**refactoring**](https://refactoring.guru/design-patterns/builder)"
  },
  {
    "path": "creational-pattern/factory-method/README.md",
    "content": "# Factory Method\n\n## 📜 Mục đích\n\n**Factory method** là một design pattern thuộc nhóm Creational, nó cung cấp một interface để tạo đối tượng cho lớp cha (superclass), nhưng cũng cho phép các lớp con (subclass) thay đổi đối tượng sẽ được tạo.\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nTưởng tượng bạn đang tạo một ứng dụng quản lý chuỗi cung ứng. Phiên bản đầu tiên của ứng dụng chỉ quản lý vận chuyển cho các xe tải, thế nên phần lớn code của bạn sẽ nằm trong lớp `Truck`. \n\nSau đó ứng dụng của bạn ngày càng phổ biến và bạn nhận được yêu cầu từ các công ty hàng hải để hợp nhất chuỗi cung ứng qua đường biển vào ứng dụng. Đấy là một thông tin tuyệt vời! Nhưng còn code thì sao?\n\n![problem](./assets/problem.png)\n\n*Việc thêm một lớp mới vào ứng dụng không hề đơn giản nếu phần lớn code đã được kết nối với các lớp hiện có.*\n\nHiện tại hầu hết code của bạn đã được ghép với lớp `Truck`. Việc thêm `Ship` vào ứng dụng sẽ yêu cầu các thay đổi với toàn bộ codebase. Và nếu bạn thêm một phương tiện vận tải nào nữa vào ứng dụng, thì bạn sẽ thay đổi code lần nữa.\n\nKết quả là bạn có một đống code tạp nham với rất nhiều điều kiện thay đổi của ứng dụng tùy thuộc vào loại đối tượng vận chuyển.\n\n## 😊 Giải pháp\n\nFactory Method gợi ý giải pháp là thay vì tạo đối tượng qua các lệnh khởi tạo trực tiếp (sử dụng toán tử `new`) thì hãy tạo bằng cách gọi phương thức *factory*. Lưu ý là đối tượng vẫn được tạo thông qua toán tử `new`, nhưng nó sẽ được gọi từ trong phương thức *factory*. Các đối tượng được trả về theo phương thức factory thường được gọi là **products**.\n\n![solution1](./assets/solution1.png)\n\n*Các lớp con có thể chỉnh sửa đối tượng trả về từ phương thức factory*\n\nThoạt nhìn, thay đổi này có vẻ vô nghĩa: chúng ta chỉ chuyển lệnh gọi *constructor* từ phần này sang phần khác của chương trình. Tuy nhiên, hãy xem xét thật kỹ lưỡng : bây giờ bạn có thể ghi đè(override) phương thức factory trong một lớp con và thay đổi `product` đang được tạo bởi phương thức này.\n\nSong, nó vẫn có một hạn chế nhỏ: các lớp con có thể trả về các kiểu `product` khác nhau chỉ khi các `product` này có lớp cơ sở hoặc interface chung. Ngoài ra, phương thức factory trong lớp cơ sở nên có kiểu trả về được khai báo là interface này. \n\n![solution2](./assets/solution2.png)\n\nVí dụ, cả hai lớp `Truck` và `Ship` đều được triển khai từ interface `Transport`, interface này khai báo một phương thức là `deliver`. Mỗi lớp sẽ triển khai phương thức này theo cách khác nhau, xe tải (truck) sẽ phân phối (deliver) hàng hoá theo đường bộ, còn tàu(ship) sẽ phân phối theo đường biển. Phương thức factory `RoadLogistics` sẽ trả về đối tượng `Truck`, còn `SeaLogistics` sẽ trả về đối tượng `Ship`.\n\n![solution3](./assets/solution3.png)\n\nĐoạn code sử dụng phương thức factory (thường được gọi là *code client*), không nhìn thấy sự khác biệt giữa những `product` trả về bởi các lớp con khác nhau. Client coi tất cả `product` là lớp trừu tượng **Transport**, đồng thời nó cũng biết các đối tượng transport phải có phương thức `deliver`. Nhưng chi tiết cách hoạt động thì nó không cần quan tâm.\n\n## 🏢 Cấu trúc\n\n![structure](./assets/structure.png)\n\n1. **Product** là interface chung cho tất cả đối tượng có thể được tạo ra bởi creator hay các lớp con của nó.\n2. **Concrete Product** là các triển khai khác nhau từ interface **Product**. Tạm hiểu là product con.\n3. **Creator** lớp này khai báo một phương thức factory trả về đối tượng product mới. Kiểu trả về của phương thức này phải tương ứng với interface **Product**. Bạn có thể định nghĩa phương thức factory là trừu tượng để tất cả lớp con triển khai phiên bản riêng của chúng. Và phương thức factory cơ sở sẽ trả về các kiểu product mặc định.\n\n4. **Concreta Creator** sẽ ghi đè (override) phương thức factory cơ sở để trả về một kiểu product mới. Không phải lúc nào phương thức factory cũng tạo ra một đối tượng mới, nó có thể trả về đối tượng đã tồn tại từ cache, object pool hay từ một nguồn nào đó.\n\n## 👨‍💻 Mã giả\n\nVí dụ này minh hoạ cách phương thức Factory có thể sử dụng để tạo các phần tử UI đa nền tảng mà không cần ghép code client với lớp UI cụ thể.\n\n![pseudocode](./assets/pseudocode.png)\n\nLớp dialog cơ sở dùng hiển thị các phần tử UI khác nhau cho hiển thị cửa sổ. Dưới các hệ điều hành khác nhau, các phần tử này có thể có vài khác biệt nhỏ, song nó vẫn phải đồng nhất. Button trên Window vẫn là button trên Linux.\n\nKhi sử dụng phương thức factory, bạn không cần viết lại các logic cho dialog vớI từng hệ điều hành. Nếu ta khai báo phương thức factory để tạo button trong lớp dialog, sau này ta có thể tạo các lớp con trả về button kiểu Windows từ phương thức factory. Lớp con sau đó sẽ kế thừa phần lớn code của dialog từ lớp cơ sở, nhờ vào phương thức factory ta có thể hiển thị các button kiểu window trên màn hình.\n\nVới pattern này khi làm việc, các lớp dialog cơ sở phải làm việc với button trừu tượng: lớp cơ sở hoặc interface cho tất cả concrete button. Theo cách này, đoạn code còn lại của dialog vẫn hoạt động, dù phải làm việc với bất kỳ kiểu button nào.\n\nTất nhiên, bạn có thể dùng cách này cho các phần tử UI khác. Tuy nhiên, với mỗi phương thức factory mà bạn thêm vào diago, ta sẽ dần tiến đến Abstract Factory pattern. Ta sẽ nói về pattern này ở các bài viết sau.\n\n```c\n// Lớp creator khai báo phương thức factory phải trả về\n// đối tượng của lớp product. Lớp con của creator tạo\n// các triển khai khác của phương thức.\n\n// Creator có thể tạo các triển khai mặc định cho\n// phương thức factory.\nclass Dialog is\n\n    abstract method createButton():Button\n\n    // Lưu ý, dù tên là creator, song không phải nhiệm vụ chính\n    // của nó là tạo product. Nó được dùng để chứa nhưng logic \n    // nghiệp vụ cốt lõi dựa trên đối tượng product trả về từ phương\n    // thức factory. Các lớp con có thể gián tiếp thay đổi logic\n    // bằng cách ghi đè lên phương thức factory và trả về kiểu \n    // product khác từ nó.\n    method render() is\n        // Gọi phương thức factory để tạo đối tượng product.\n        Button okButton = createButton()\n        // Sử dụng product.\n        okButton.onClick(closeDialog)\n        okButton.render()\n\n\n// Concrete creator ghi đè lên phương thức factory để \n// thay đổi kiểu product trả về.\nclass WindowsDialog extends Dialog is\n    method createButton():Button is\n        return new WindowsButton()\n\nclass WebDialog extends Dialog is\n    method createButton():Button is\n        return new HTMLButton()\n\n// Interface product khai báo phương thức cho tất cả \n// concrete product cần triển khai.\ninterface Button is\n    method render()\n    method onClick(f)\n\n// Concrete product tạo ra các triển khai với interface product.\nclass WindowsButton implements Button is\n    method render(a, b) is\n        // Hiển thị button kiểu Windows\n    method onClick(f) is\n        // Đánh đấu sự kiện click trên hệ điều hành.\n\nclass HTMLButton implements Button is\n    method render(a, b) is\n        // Hiển thị button dưới dạng HTML\n    method onClick(f) is\n        // Đánh dấu sự kiện click trên trình duyệt.\n\n\nclass Application is\n    field dialog: Dialog\n\n    // Ứng dụng chon kiểu creator dựa trên cấu hình \n    // hiện tại hoặc môi trường thiết lập.\n    method initialize() is\n        config = readApplicationConfigFile()\n\n        if (config.OS == \"Windows\") then\n            dialog = new WindowsDialog()\n        else if (config.OS == \"Web\") then\n            dialog = new WebDialog()\n        else\n            throw new Exception(\"Error! Unknown operating system.\")\n\n    // Code client làm việc với thực thể của concrete creator,\n    // thông qua interface cơ sở. Miễn là client vẫn làm việc với\n    // creator thông qua interface, bạn có thể chuyển nó vào bất\n    // kỳ lớp con nào của creator.\n    method main() is\n        this.initialize()\n        dialog.render()\n```\n\n## 💡 Ứng dụng\n\n🐞 **Sử dụng phương thức Factory khi bạn không biết chính xác kiểu và phụ thuộc của đối tượng mà code bạn sẽ làm việc**\n\n⚡ Phương pháp Factory phân tách code khởi tạo product với code sử dụng lại product. Do đó việc mở rộng code khởi tạo product với phần code còn lại sẽ dễ dàng hơn.\n\n🐞 **Sử dụng phương thức Factory khi bạn cung cấp cho người dùng thư viện hay framework với cách mở rộng các thành phần trong nó**\n\n⚡ Kế thừa có lẽ là cách dễ nhất để mở  rộng các hành vi mặc định của một thư viện hay framework. Nhưng làm thế nào để framework nhận diện được đâu là lớp con của bạn, đâu là thành phần tiêu chuẩn. Giải pháp ở đây là làm giảm code khởi tạo component của framework thành một phương thức factory duy nhất và cho phép bất kỳ ai ghi đè (override) lên phương thức để thêm các phần mở rộng cho component đó.\n\nVí dụ, bạn đang tạo một ứng dụng dựa trên một framework UI mã nguồn mở. Bây giờ bạn muốn có một button dạng tròn cho ứng dụng, nhưng framework chỉ hỗ trợ button vuông. Thế nên bạn cần mở rộng lớp tiêu chuẩn `Button` thành lớp con `RoundButton`. Bây giờ bạn cần nói cho lớp chính `UIFramework` rằng sử dụng lớp con button mới thay vì mặc định. Để làm được điều đó, bạn tạo lớp con `UIWithRoundButtons` từ lớp cơ sở của framework và ghi đè lên phương thức `createButton`. Trong khi phương thức ở lớp cơ sở trả về đối tượng `Button` thì lớp con của bạn sẽ trả về đối tượng `RoundButton`. Bây giờ bạn sẽ sử dụng `UIWithRoundButtons` thay vì `UIFramework`.\n\n🐞 **Sử dụng phương thức Factory khi bạn muốn tiết kiệm tài nguyên hệ thống bằng cách sử dụng lại đối tượng hiện có thay vì tạo mới chúng mỗi lần**\n\n⚡  Bạn thường gặp phải yêu cầu này khi làm việc với các đối tượng lớn, sử dụng nhiều tài nguyên như kết nối cơ sở dữ liệu, hệ thống file, tài nguyên mạng,..\n\nBây giờ hãy nghĩ về những việc phải làm với đối tượng hiện có:\n\n1. Bạn cần nơi để lưu trữ tất cả các đối tượng đã tạo.\n2. Khi ai đó yêu cầu một đối tượng, chương trình sẽ thực hiện tìm kiếm đối tượng đó trong pool.\n3. ...và trả về cho code client.\n4. Nếu không có đối tượng, chương trình sẽ tạo ra một đối tượng mới (và thêm nó vào pool).\n\nCó khá nhiều code, và ta phải đặt chúng vào một nơi duy nhất để không rối chương trình do các đoạn code có thể bị trùng. Có lẽ nơi rõ ràng và thuận tiện nhất mà code này có thể được đặt là tại hàm khởi tạo của lớp có các đối tượng mà ta đang cố gắng sử dụng lại. Tuy nhiên, một hàm khởi tạo luôn phải trả về các đối tượng mới theo định nghĩa. Nó không thể trả lại các phiên bản hiện có.\n\nDo đó, bạn cần phải có một phương thức có khả năng tạo các đối tượng mới cũng như sử dụng lại các đối tượng hiện có. Và đó chính là phương thức Factory.\n\n## 📋 Triển khai\n\n1. Tạo tất cả product theo cùng một interface. Interface này nên khai báo phương thức có ý nghĩa với tất cả product.\n\n2. Thêm phương thức factory trống vào lớp creator. Kiểu trả về của phương thức nên tương ứng với interface product chung.\n\n3. Trong code creator tìm tất cả tham chiếu đến hàm khởi tạo product. Từng cái một, thay thế nó với lệnh gọi phương thức factory, trong khi trích xuất code tạo product vào phương thức factory. Bạn cần thêm tham số mẫu vào phương thức factory để điều khiển kiểu trả về của product.\n\n4. Bây giờ, tạo tập hợp lớp con của creator cho từng kiểu product trong phương thức factory. Ghi đè lên phương thức factory ở lớp con và trích xuất các bit phù hợp từ hàm khởi tạo với phương thức cơ sở.\n\n5. Nếu có quá nhiều kiểu product và nó không phù hợp tạo lớp con cho chúng, ta có thể tái sử dụng tham số điều khiển từ lớp cở sở ở lớp con. Ví dụ, bạn có một hệ thống phân cấp các lớp như sau: lớp cơ sở `Mail` với hai lớp con: `AirMail` và `GroundMail`; lớp `Transport` có `Plane`, `Truck` và `Train`. Trong khi lớp `AirMail` chỉ dùng đối tượng `Plane`, thì `GroundMail` làm việc với cả hai đối tượng `Truck` và `Train`. Bạn có thể tạo lớp con (tạm gọi `TrainMail`) để xử lý cả hai trường hợp, nhưng cũng có lựa chọn khác. Code client có thể gửi tham số vào phương thức factory của `GroundMail` để điều khiển kiểu product mà nó muốn nhận.\n\n6. Sau cùng, nếu phương thức factory ở lớp cơ sở trống, bạn có thể chuyển nó thành trừu tượng(abstract). Nếu còn sót lại gì đó thì ta sẽ thiết lập đó là hành vi mặc định của phương thức.\n\n## ⚖️ Ưu nhược điểm\n\n**Ưu điểm**\n\n ✔️ Tránh được kết hợp quá chặt chẽ giữa creator và concrete product.\n\n ✔️ *Single Responsibility Principle*. Bạn có thể di chuyển code tạo product vào một nơi trong chương trình, giúp code hỗ trợ dễ dàng hơn.\n\n ✔️  *Open/Closed Principle*. Bạn có thể thêm các kiểu product mới vào chương trình, mà không làm ảnh hưởng đến code client hiện tại.\n\n**Nhược điểm**\n\n❌ Code có thể trở nên phức tạp khi bạn thêm vào quá nhiều lớp con để triển khai pattern. Trường hợp tốt nhất là khi bạn triển khai pattern bằng cách sử dụng hệ thống phân cấp của lớp creator.\n \n## 🔁 Quan hệ với các pattern khác\n\nNhiều pattern bắt đầu bằng cách sử dụng **Factory Method** (ít phức tạp hơn và có thể tùy chỉnh nhiều hơn thông qua các lớp con) và phát triển theo hướng **Abstract Factory**, **Prototype** hoặc **Builder** (linh hoạt hơn nhưng phức tạp hơn).\n\nCác lớp **Abstract Factory** thường dựa trên một tập hợp các **Factory Method**, nhưng bạn cũng có thể sử dụng **Prototype** để cấu trúc các phương thức trên các lớp này.\n\nBạn có thể sử dụng **Factory Method** cùng với **Iterator** để cho phép các lớp con của collection trả về các kiểu vòng lặp khác nhau tương thích với các collection.\n\n**Prototype** không dựa trên sự kế thừa, vì vậy nó không có nhược điểm. Mặt khác, **Prototype** yêu cầu khởi tạo nhân bản đối tượng phức tạp. **Factory Method** dựa trên kế thừa nhưng không yêu cầu bước khởi tạo.\n\n**Factory Method** là một chuyên môn hóa của **Template Method**. Đồng thời, **Factory Method** có thể đóng vai trò là một bước trong một **Template Method** lớn.\n\n# Nguồn\n\n[**refactoring**](https://refactoring.guru/design-patterns/factory-method)\n"
  },
  {
    "path": "creational-pattern/prototype/README.md",
    "content": "# Prototype\n\n## 📜 Mục đích\n\n**Prototype** là một design pattern thuộc nhóm creational, giúp bạn sao chép một đối tượng mà code của bạn sẽ không phụ thuộc vào lớp của đối tượng đó.\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nGiả sử bạn đang có một đối tượng và bạn muốn tạo ra bản sao của nó. Vậy làm thế nào ? Đầu tiên bạn sẽ tạo ra một đối tượng mới có cùng lớp, sau đó bạn sẽ lấy giá trị từ tất cả các trường của đối tượng gốc và gán nó sang cho đối tượng mới.\n\nHay lắm ! Nhưng nó có vấn đề. Không phải tất cả đối tượng đều có thể sao chép theo cách này vì có thể một vài trường của nó là riêng tư (private) và không thể truy cập từ bên ngoài đối tượng.\n\n![problem](./assets/problem.png)\n\n*Copy đối tượng từ bên ngoài không phải lúc nào cũng tốt*\n\nCó nhiều hơn một vấn đề với cách tiếp cận này, là khi bạn biết lớp của đối tượng mà bạn tạo bản sao, code của bạn sẽ trở nên phụ thuộc vào lớp đó. Nếu điều này chưa làm bạn lo lắng thì còn một vấn đề nữa. Là thỉnh thoảng bạn chỉ biết interface của đối tượng, chứ không biết đến lớp cụ thể, khi đó tham số trong các phương thức của bạn sẽ chấp nhận bất kỳ đối tượng nào theo interface đấy.\n\n## 😊 Giải pháp\n\nPattern Prototype uỷ thác quá trình sao chép cho các đối tượng thực đang được sao chép. Pattern này khai báo một interface chung hỗ trợ sao chép cho tất cả đối tượng. Interface này giúp bạn sao chép đối tượng mà không cần ghép code của bạn với lớp của đối tượng. Thông thường, interface như vậy chỉ bao gồm một phương thức `clone`.\n\nTriển khai phương thức `clone` là như nhau với mọi lớp. Phương thức tạo một đối tượng của lớp hiện tại và chuyển tất cả trường giá trị của đối tượng cũ sang đối tượng mới. Thậm chí có thể sao chép cả trường riêng tư vì phần lớn ngôn ngữ lập trình cho phép đối tượng truy cập trường riêng tư của đối tượng khác nếu chúng cùng thuộc một lớp.\n\nĐối tượng hỗ trợ sao chép gọi là *prototype*. Khi đối tượng của bạn có hàng chục trường và hàng trăm cấu hình khả khi, nhân bản chúng có thể xem như một giải pháp thay thế cho tạo lớp con.\n\n![solution](./assets/solution.png)\n\n*Các prototype tạo sẵn có thể thay thế cho phân lớp.*\n\nCách mà nó hoạt động: bạn tạo một tập hợp các đối tượng, được cấu hình theo nhiều cách khác nhau. Khi bạn cần một đối tượng giống như đối tượng bạn đã cấu hình, bạn chỉ cần sao chép một prototype thay vì xây dựng một đối tượng mới từ đầu.\n\n## 🚗 Thế Giới Thực\n\nTrong cuộc sống thực, các prototype được sử dụng để thực hiện các thử nghiệm khác nhau trước khi bắt đầu sản xuất hàng loạt một sản phẩm. Tuy nhiên, trong trường hợp này các prototype không tham gia vào bất kỳ quá trình sản xuất thực nào, nó chỉ đóng vai trò thụ động. Vì các prototype trong công nghiệp không thực sự tự sao chép.\n\n![analogy](./assets/analogy.png)\n\nMột ví dụ thực nữa của pattern này quá trình nguyên phân trong sinh học. Sau khi nguyên phân, một cặp tế bào giống hệt nhau được hình thành. Tế bào gốc lúc này hoạt động như một prototype và đóng vai trò chủ động.\n\n## 🏢 Cấu trúc\n\n### Triển khai cơ bản\n\n![structure1](./assets/structure1.png)\n\n1. **Prototype** là interface khai báo phương thức sao chép. Trong đa số trường hợp, nó chỉ có một phương thức `clone`.\n2. **Concrete Prototype** lớp triển khai phương thức sao chép. Ngoài việc sao chép dữ liệu của đối tượng ban đầu sang bản sao, phương pháp này cũng có thể xử lý một số trường hợp của quá trình sao chép liên quan đến việc sao chép các đối tượng được liên kết, gỡ rối các phụ thuộc đệ quy, ...\n3. **Client**  có thể tạo một bản sao của bất kỳ đối tượng nào theo interface prototype.\n\n### Triển khai prototype registry\n\n![structure2](./assets/structure2.png)\n\n1. **Prototype Registry** cung cấp cách để truy cập dễ dàng các prototype được sử dụng thường xuyên. Nó lưu trữ một tập hợp đối tượng đã tạo sẵn cho việc sao chép. Prototype registry đơn giản nhất là là một hashmap `name → prototype`. Tuy nhiên, nếu bạn cần các tiêu chí tìm kiếm tốt hơn, bạn có thể tự xây dựng một phiên bản registry mạnh mẽ hơn.\n\n## 👨‍💻 Mã giả\n\nTrong ví dụ này, Prototype Pattern cho phép bạn tạo các bản sao chính xác của các đối tượng hình học mà không cần ghép code với các lớp của chúng.\n\n![pseudocode](./assets/pseudocode.png)\n\nTất cả các lớp hình dạng theo sau một interface, cung cấp phương thức sao chép. Lớp con có thể gọi phương thức sao chép của lớp cha trước khi sao chép các trường giá trị của chính nó vào đối tượng kết quả. \n\n```c\n// Prototype cơ sở.\nabstract class Shape is\n    field X: int\n    field Y: int\n    field color: string\n\n    // Hàm khởi tạo thông thường.\n    constructor Shape() is\n        // ...\n\n    // Hàm khởi tạo prototype. Đối tượng rỗng được tạo\n    // với giá trị từ đối tượng đã tồn tại.\n    constructor Shape(source: Shape) is\n        this()\n        this.X = source.X\n        this.Y = source.Y\n        this.color = source.color\n\n    // Phương thức clone trả về một trong những lớp con Shape.\n    abstract method clone():Shape\n\n\n// Concrete prototype. Phương thức sao chép tạo đối tượng mới\n// và truyền vào hàm khởi tạo. Cho đến khi hàm khởi tạo kết thúc\n// nó sẽ tham chiếu đến bản sao. Do đó không có ai có thể truy cập \n// đến bản sao chưa hoàn chỉnh. Nó giữ cho bản sao nhất quán.\nclass Rectangle extends Shape is\n    field width: int\n    field height: int\n\n    constructor Rectangle(source: Rectangle) is\n        // Lệnh gọi hàm khởi tạo cha là cần thiết\n        // để sao chép trường riêng tư được định\n        // nghĩa trong lớp cha\n        super(source)\n        this.width = source.width\n        this.height = source.height\n\n    method clone():Shape is\n        return new Rectangle(this)\n\n\nclass Circle extends Shape is\n    field radius: int\n\n    constructor Circle(source: Circle) is\n        super(source)\n        this.radius = source.radius\n\n    method clone():Shape is\n        return new Circle(this)\n\n\n// Đâu đó trong code client.\nclass Application is\n    field shapes: array of Shape\n\n    constructor Application() is\n        Circle circle = new Circle()\n        circle.X = 10\n        circle.Y = 10\n        circle.radius = 20\n        shapes.add(circle)\n\n        Circle anotherCircle = circle.clone()\n        shapes.add(anotherCircle)\n        // Biến `anotherCircle` bao gồm bản sao \n        // chính xác của đối tượng `circle`.\n\n        Rectangle rectangle = new Rectangle()\n        rectangle.width = 10\n        rectangle.height = 20\n        shapes.add(rectangle)\n\n    method businessLogic() is\n        // Prototype chắc chắn vì nó giúp bạn tạo ra bản sao của đối\n        // tượng mà không cần biết bất cứ điều gì về kiểu của nó.\n        Array shapesCopy = new Array of Shapes.\n\n        // Ví dụ, bạn không biết chính xác phần tử trong mảng shape.\n        // Tất cả những gì ta biết chỉ là đấy là hình dạng.\n        // Nhưng nhờ tính đa hình, khi ta gọi phương thức `clone`\n        // trên một hình dạng, chương trình kiểm tra lớp có thực và\n        // chạy phương thức clone phù hợp đã định nghĩa trong lớp.\n        // Đó là lý do vì sao ta nhận được bản sao phù hợp thay vì \n        // một mảng đối tượng Shape thông thường.\n        foreach (s in shapes) do\n            shapesCopy.add(s.clone())\n\n        // Mảng `shapeCopy` bao gồm các bản sao chính xác\n        // của mảng `shape`.\n```\n\n## 💡 Ứng dụng\n\n**🐞 Sử dụng Prototype khi code bạn không muốn phụ thuộc vào một lớp cụ thể của đối tượng cần sao chép**\n\n⚡ Chuyện này xảy ra khi bạn làm việc với đối tượng được truyền đến từ code bên thứ ba thông qua một vài interface. Các lớp cụ thể của đối tượng này là không xác định nên bạn không thể phụ thuộc nó, ngay cả khi muốn. \n\nPattern Prototype cung cấp cho code client một interface chung để làm việc với tất cả đối tượng hỗ trợ sao chép. Interface này giúp code client độc lập với lớp cụ thể từ đối tượng mà nó sao chép.\n\n**🐞 Sử dụng Prototype khi bạn muốn giảm số lượng lớp con, chỉ khác nhau về cách chúng khởi tạo các đối tượng tương ứng**\n\n⚡ Pattern Prototype cho phép bạn sử dụng một tập hợp các đối tượng được tạo sẵn, được cấu hình theo nhiều cách khác nhau, là prototype.\n\nThay vì khởi tạo một lớp con phù hợp với một số cấu hình, client chỉ cần tìm kiếm một prototype thích hợp và sao chép nó.\n\n## 📋 Triển khai\n\n1. Tạo interface prototype và khai báo phương thức sao chép trong đó. Hoặc thêm phương thức vào tất cả các lớp của hệ phân cấp lớp, nếu bạn có.\n\n2. Lớp prototype phải định nghĩa hàm khởi tạo thay thế để chấp nhận đối tượng của lớp đó như một tham số. Hàm khởi tạo phải sao chép giá trị từ tất cả trường đã định nghĩa trong lớp từ đối tượng được truyền vào đối tượng mới được tạo. Nếu bạn đang thay đổi một lớp con, bạn phải gọi hàm khởi tạo cha để cho phép lớp cha xử lý việc sao chép các trường riêng tư của nó.\n\n    Nếu ngôn ngữ lập trình của bạn không hỗ trợ phương thức overloading, bạn phải định nghĩa phương thức đặc biệt cho sao chép đối tượng dữ liệu. Hàm khởi tạo là một nơi tiện lợi để làm điều này vì nó cung cấp kết quả đối tượng ngay sau khi bạn gọi toán tử `new`.\n\n3. Phương thức sao chép thường chỉ bao gồm một dòng: chạy một toán tử `new` với phiên bản prototype của hàm khởi tạo. Lưu ý rằng mọi lớp phải ghi đè(override) rõ ràng phương thức sao chép và sử dụng tên lớp của chính nó cùng với toán tử `new`. Nếu không, phương thức sao chép có thể tạo ra một đối tượng của lớp cha.\n\n4. Tuỳ chọn, tạo một prototype registry để lưu trữ một danh mục các prototype thường được sử dụng. \n\n    Bạn có thể triển khai registry như một lớp factory hoặc đặt nó vào một lớp prototype cơ sở với phương thức tĩnh cho tìm nạp prototype. Phương thức này tìm kiếm prototype dựa trên các tiêu chí tìm kiếm mà code client truyền đến phương thức. Tiêu chí có thể là một chuỗi đơn giản hoặc cũng có thể là một tập hợp các tham số tìm kiếm phức tạp. Sau khi tìm thấy prototype thích hợp, registry sẽ sao chép nó và trả lại bản sao cho client.\n    \n5. Cuối cùng, thay thế các lệnh gọi trực tiếp đến các hàm khởi tạo của lớp con bằng các lệnh gọi đến phương thức factory của prototype registry.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ Bạn có thể sao chép đối tượng mà không cần quan tâm đến lớp cụ thể.\n\n✔️ Bạn có thể tránh code khởi tạo lặp đi lặp lại bằng việc sao chép các prototype có sẵn.\n\n✔️ Bạn có thể tạo các đối tượng phức tạp thuận tiện.\n\n✔️ Bạn nhận được một giải pháp thay thế cho kế thừa khi phải xử lý các cấu hình cho các đối tượng phức tạp.\n\n### Nhược điểm\n\n❌ Sao chép các đối tượng phức tạp có tham chiếu vòng tròn có thể rất khó.\n\n## 🔁 Quan hệ với các pattern khác\n\nNhiều pattern bắt đầu bằng cách sử dụng **Factory Method** (ít phức tạp hơn và có thể tùy chỉnh nhiều hơn thông qua các lớp con) và phát triển theo hướng **Abstract Factory**, **Prototype** hoặc **Builder** (linh hoạt hơn nhưng phức tạp hơn).\n\nCác thiết kế sử dụng nhiều **Composite** và **Decorator** thường có thể được hưởng lợi từ việc sử dụng **Prototype**. Áp dụng pattern cho phép bạn sao chép các cấu trúc phức tạp thay vì xây dựng lại chúng từ đầu.\n\nCác lớp **Abstract Factory** thường dựa trên một tập hợp các **Factory Method**, nhưng bạn cũng có thể sử dụng **Prototype** để cấu trúc các phương thức trên các lớp này.\n\n**Prototype** không dựa trên sự kế thừa, vì vậy nó không có nhược điểm. Mặt khác, **Prototype** yêu cầu khởi tạo nhân bản đối tượng phức tạp. **Factory Method** dựa trên kế thừa nhưng không yêu cầu bước khởi tạo.\n\n**Prototype** có thể hữu ích khi bạn cần lưu các bản sao của **Commands** vào lịch sử.\n\nĐôi khi **Prototype** có thể là một giải pháp thay thế đơn giản hơn cho **Memento**. Điều này hoạt động nếu đối tượng, trạng thái mà bạn muốn lưu trữ trong lịch sử, khá đơn giản và không có liên kết đến tài nguyên bên ngoài hoặc các liên kết dễ thiết lập lại.\n\nTất cả các **Abstract Factory**, **Builder** và **Prototype** đều có thể được triển khai dưới dạng các **Singleton**.\n\n# Nguồn\n\n[**refactoring**](https://refactoring.guru/design-patterns/prototype)"
  },
  {
    "path": "creational-pattern/singleton/README.md",
    "content": "# Singleton\n\n## 📜 Mục đích\n\n**Singleton** là một design pattern thuộc nhóm creational giúp bạn tạo ra một lớp chỉ với một thực thế duy nhất, trong khi cung cấp điểm truy cập toàn cục cho thực thế đấy.\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nSingleton cùng lúc giải quyết hai vấn đề, vi phạm đến *Nguyên tắc Trách nhiệm đơn lẻ (Single Responsibility Principle)*:\n\n1. **Đảm bảo mỗi lớp chỉ có một thực thể**: Tại sao bất kỳ ai cũng muốn kiểm soát số lượng thực thể (instance) mà một lớp có ? Lý do phổ biến nhất là để quản lý truy cập đến các tài nguyên chung, vd như cơ sở dữ liệu hay file. \n\nTưởng tượng, bạn đã tạo một đối tượng nhưng sau một thời gian bạn quyết định tạo một đối tượng mới. Bởi vì Singleton bảo đảm chỉ có duy nhất một thực thể được tạo ra, nên thay vì nhận một đối tượng mới hoàn toàn bạn sẽ nhận về đối tượng đã được tạo.\n\nLưu ý: Điều này không thể thực thi với các hàm khởi tạo (constructor) thông thường vì chúng sẽ luôn trả về đối tượng mới.\n\n![problem](./assets/problem.png)\n\n*Client sẽ không nhận ra được họ đang làm việc với một đối tượng mọi lúc*\n\n2. **Cung cấp một điểm truy cập toàn cục cho thực thể**: Hãy nhớ lại các biến toàn cục mà bạn đã dùng để lưu trữ một số đối tượng thiết yếu. Mặc dù khá tiện dụng nhưng chúng lại không an toàn vì bất kỳ đoạn code nào cũng có khả năng ghi đè lên nội dung của biến đó và làm hỏng chương trình.\n\nGiống như biến toàn cục, Singleton giúp bạn truy cập đến các đối tượng ở bất cứ đâu trong chương trình. Tuy nhiên, không như biến, nó sẽ bảo vệ các thực thể khỏi bị ghi đè bởi code khác.\n\nMặt khác của vấn đề: bạn không muốn code giải quyết vấn đề #1 bị phân tán khắp chương trình. Sẽ tốn hơn nếu có nó trong một lớp, đặc biệt nếu phần còn lại của code bạn đã phụ thuộc vào nó. \n\n## 😊 Giải pháp\n\nTất cả triển khai của Singelton đều có hai bước chung là:\n- Mặc định các hàm khởi tạo là riêng tư, để tránh các đối tượng khác sử dụng toán từ `new` với lớp Singleton.\n- Tạo một phương thức tĩnh hoạt động như một hàm khởi tạo. Bên trong phương thức này, sẽ gọi đến hàm khởi tạo riêng tư để tạo một đối tượng và lưu nó vào một trường tĩnh. Tất cả lệnh gọi theo sau phương thức này trả về một đối tượng cache.\n\nNếu code của bạn có quyền truy cập vào lớp Singleton thì nó có thể gọi phương thức tĩnh của Singleton. Vì vậy, bất cứ khi nào phương thức đó được gọi, sẽ có cùng một đối tượng được trả về.\n\n## 🚗 Thế Giới Thực\n\nChính phủ là một ví dụ điển hình của pattern Singleton. Mỗi quốc gia chỉ có thể có một chính phủ chính thức. Bất kể danh tính cá nhân của các cá nhân đại diện chính phủ, danh hiệu, “Chính phủ X”, đều là điểm truy cập toàn cục để xác định danh tính nhóm người phụ trách.\n\n## 🏢 Cấu trúc\n\n![structure](./assets/structure.png)\n\n1. **Lớp Singleton** khai báo phương thức tĩnh `getInstance` để trả về cùng một thực thể của lớp đó.\n\nHàm khởi tạo Singleton sẽ bị ẩn ở code client, gọi phương thức `getInstance` là cách duy nhất để lấy đối tượng Singleton.\n\n## 👨‍💻 Mã giả\n\nTrong ví dụ này, cơ sở dữ liệu sẽ kết nối với một lớp hoạt động như một Singleton. Nó không có hàm khởi tạo công khai, cách duy nhất để lấy đối tượng là gọi phương thức `getInstane`. Phương thức này lưu đối tượng tạo trong lần đầu vào cache và sử dụng nó cho các lần gọi tiếp theo.\n\n```c\n// Lớp Database định nghĩa phương thức `getInstance` để giúp\n// client truy cập vào cùng đối tượng mà cơ sở dữ liệu kết\n// nối trong suốt chương trình.\nclass Database is\n    // Trường này để lưu trữ thực thể singleton nên khai\n    // báo là tĩnh (static)\n    private static field instance: Database\n\n    // Hàm khởi tạo singleton luôn luôn là riêng tư\n    // để tránh khởi tạo trực tiếp với toán tử `new`.\n    private constructor Database() is\n        // Một vài code khởi tạo ở đây, như là\n        // kết nối đến server của cơ sở dữ liệu.\n\n    // Phương thức tĩnh điều khiển truy cập đến thực thể\n    // singleton.\n    public static method getInstance() is\n        if (Database.instance == null) then\n            acquireThreadLock() and then\n                // Đảm bảo rằng thực thể chưa được tạo bởi \n                // luồng(thread) khác trong khi luồng này đang\n                // đợi giải phóng lock.\n                if (Database.instance == null) then\n                    Database.instance = new Database()\n        return Database.instance\n\n    // Cuối cùng, bất kỳ singleton nào cũng có một vài logic nghiệp vụ\n    // để có thể thực thi các thực thể của nó.\n    public method query(sql) is\n        // Ví dụ, tất cả truy vấn cơ sở dữ liệu của ứng dụng\n        // trong phương thức này. Do đó bạn có thể đặt logic\n        // điều tiết hoặc cache vào đây.\n\nclass Application is\n    method main() is\n        Database foo = Database.getInstance()\n        foo.query(\"SELECT ...\")\n        // ...\n        Database bar = Database.getInstance()\n        bar.query(\"SELECT ...\")\n        // Biến `bar` sẽ bao gồm cùng đối tượng với\n        // biến `foo`.\n```\n\n## 💡 Ứng dụng\n\n**🐞 Sử dụng mẫu Singleton khi một lớp trong chương trình của bạn chỉ nên có một thực thể duy nhất cho tất cả client**\n\n⚡ Thường thấy khi dùng một đối tượng cơ sở dữ liệu duy nhất kết nối đến các phần khác nhau trong ứng dụng. Singleton vô hiệu hoá tất cả cách tạo đối tượng của lớp trừ phương thức tạo đặc biệt.\n\n**🐞 Sử dụng Singleton khi bạn cần kiểm soát chặt chẽ hơn đối với các biến toàn cục**\n\n⚡ Không giống như các biến toàn cục, Singleton đảm bảo rằng không có gì khác ngoại trừ chính lớp Singleton có thể thay đổi được thực thể được lưu.\n\n*Lưu ý rằng bạn luôn có thể điều chỉnh giới hạn thực thể trong Singleton và cho phép tạo bất kỳ số lượng thực thể nào. Đoạn code duy nhất cần thay đổi là phần thân của phương thức `getInstance`.*\n\n## 📋 Triển khai\n\n1. Thêm một trường tĩnh vào lớp cho lưu trữ thực thể singleton.\n\n2. Khai báo phương thức tĩnh công khai cho lấy thực thể singleton.\n\n3. Triển khai \"lazy initialization\" bên trong phương thức tĩnh. Nó tạo ra đối tượng mới cho lần gọi đầu tiên và đặt vào trong trường tĩnh. Phương thức luôn trả về thực thể đó cho tất cả gần gọi tiếp theo.\n\n4. Thiết lập hàm khởi tạo riêng tư cho lớp. Phương thức tĩnh của lớp vẫn có thể gọi hàm khởi tạo nhưng không thể gọi đối tượng khác.\n\n5. Đi đến code client và thay thế tất cả lệnh gọi trực tiếp đến hàm khởi tạo singleton bằng cách gọi đến phương thức khởi tạo tĩnh.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ Bạn có thể chắc chắn mỗi lớp chỉ có một thực thể.\n\n✔️ Bạn có điểm truy cập toàn cục đến thực thể đó.\n\n✔️ Đối tượng singleton được tạo chỉ một lần duy nhất cho lệnh gọi đầu tiên.\n\n### Nhược điểm\n\n❌ Như đã nói, cả hai vấn đề của Singleton đều vi phạm *Nguyên tắc trách nhiệm đơn lẻ*.\n\n❌ Singleton có thể giấu đi các thiết kế tệ. Ví dụ như khi các thành phần trong chương trình biết quá nhiều về nhau.\n\n❌ Pattern yêu cầu được xử lý đặc biệt trong môi trường đa luồng, để nhiều luồng sẽ không tạo ra một đối tượng Singleton nhiều lần.\n\n❌ Gặp khó khăn khi thực hiện unit test cho code client của Singleton, vì các framework test dựa trên kế thừa khi tạo ra các đối tượng giả. Và hàm khởi tạo của lớp Singleton là private cùng với việc ghi đè các phương thức tĩnh là không thể trong hầu hết các ngôn ngữ, nên bạn sẽ cần phải nghĩ ra một cách sáng tạo để mô phỏng lớp singleton. Hoặc chỉ không thực hiện test. Hoặc không sử dụng Singleton. \n\n## 🔁 Quan hệ với các pattern khác\n\nMột lớp **Facade** thường có thể được chuyển đổi thành **Singleton** vì một đối tượng facade duy nhất là đủ trong hầu hết các trường hợp.\n\n**Flyweight** sẽ giống với **Singleton** nếu bạn bằng cách nào đó giảm được tất cả các trạng thái được chia sẻ của các đối tượng xuống chỉ còn một đối tượng flyweight. Nhưng có hai điểm khác biệt cơ bản giữa các pattern này:\n\n- Chỉ nên có một thực thể **Singleton**, trong khi lóp **Flyweight** có thể có nhiều thực thể với các trạng thái nội tại khác nhau.\n- Đối tượng **Singleton** có thể thay đổi được. Đối tượng **Flyweight** là bất biến.\n\nTất cả các **Abstract Factory**, **Builder** và **Prototype** đều có thể được triển khai dưới dạng các **Singleton**.\n\n# Nguồn\n\n[**refactoring**](https://refactoring.guru/design-patterns/singleton)"
  },
  {
    "path": "structural-pattern/README.md",
    "content": "# Structural Design Patterns\n\nStructural Pattern giải thích cách tập hợp các đối tượng và lớp thành các cấu trúc lớn hơn, trong khi vẫn giữ cho cấu trúc linh hoạt và hiệu quả.\n\n## Adapter\n\n![adapter-mini](./assets/adapter-mini.png)\n\nCho phép các đối tượng có interface không tương thích cộng tác với nhau.\n\n## Bridge\n\n![bridge-mini](./assets/bridge-mini.png)\n\nGiúp bạn tách một lớp khổng lồ hoặc một tập hợp lớp có quan hệ gần gũi với nhau thành hai hệ thống phân cấp lớp riêng biệt là - abstraction(trừu tượng) và implementation(triển khai) - có thể phát triển độc lập với nhau.\n\n## Composite\n\n![composite-mini](./assets/composite-mini.png)\n\nGiúp bạn sắp xếp các đối tượng thành cấu trúc cây và sau đó làm việc với các cấu trúc này như thể chúng là các đối tượng riêng lẻ.\n\n## Decorator\n\n![decorator-mini](./assets/decorator-mini.png)\n\nGiúp bạn thêm một hành vi mới vào đối tượng bằng cách đặt đối tượng đó vào trong một đối tượng đặc biệt có chứa hành vi đấy\n\n## Facade\n\n![facade-mini](./assets/facade-mini.png)\n\nCung cấp interface đơn giản cho thư viện, framework hoặc bất kỳ tập hợp lớp phức tạp nào khác.\n\n## Flyweight\n\n![flyweight-mini](./assets/flyweight-mini.png)\n\nGiúp bạn chỉnh các đối tượng vừa với lượng RAM khả dụng bằng các chia sẻ trạng thái chung giữa các đối tượng thay vì giữ tất cả dữ liệu ở mỗi đối tượng.\n\n## Proxy\n\n![proxy-mini](./assets/proxy-mini.png)\n\nCho phép bạn cung cấp một vật thay thế hoặc vật giữ chỗ cho một đối tượng khác. Một proxy kiểm soát quyền truy cập đến đối tượng ban đầu, cho phép bạn thực hiện điều gì đó trước hoặc sau khi yêu cầu được chuyển đến đối tượng ban đầu."
  },
  {
    "path": "structural-pattern/adapter/README.md",
    "content": "# Adapter\n\n## 📜 Mục đích\n\n**Adapter** là một design pattern thuộc nhóm structural cho phép các đối tượng có interface không tương thích cộng tác với nhau.\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nTượng tượng bạn đang tạo một ứng dụng giám sát thị trường chứng khoán. Ứng dụng sẽ tải dữ liệu chứng khoán từ nhiều nguồn dưới dạng XML, và hiển thị nó dưới dạng biểu đồ và sơ đồ cho người dùng.\n\nVào một thời điểm nào đó, bạn quyết định cải tiến ứng dụng bằng việc tích hợp một thư viện bên thứ ba cho phân tích dữ liệu. Nhưng có một vấn đề là thư viện này chỉ làm việc với dữ liệu dạng JSON. \n\n![problem](./assets/problem.png)\n\n*Bạn không thể sử dụng thư viện phân tích vì nó yêu cầu dữ liệu không tương thích với ứng dụng của bạn*\n\nNếu bạn thay đổi thư viện để nó làm việc với XML nó có thể ảnh hưởng đến những đoạn code hiện có trong thư viện. Hoặc tệ hơn là ngay từ đầu bạn không được phép truy cập đến mã nguồn của thư viện. Nên cách tiếp cận này là bất khả thi.\n\n## 😊 Giải pháp\n\nBạn có thể tạo ra một *adapter*, là một đối tượng đặc biệt có thể chuyển đổi interface của một đối tượng cho các đối tượng khác hiểu được nó.\n\nAdapter sẽ bọc một đối tượng để giấu đi sự phức tạp đằng sau chuyển đổi đấy. Đối tượng được bọc thậm chí còn không biết gì về adapter. Ví dụ như bạn có thể bọc một đối tượng có đơn vị đo lường là kilomet và met, với bộ adapter sẽ chuyển đổi tất cả dữ liệu sang các đơn vị là feet và miles.\n\nAdapter không chỉ có thể chuyển đổi dữ liệu thành nhiều định dạng khác nhau mà còn có thể giúp các đối tượng có interface khác nhau cộng tác. Đây là cách nó hoạt động:\n1. Adapter lấy interface và tương thích của nó với một đối tượng đã tồn tại.\n2. Sử dụng interface, đối tượng đã tồn tại có thể gọi đến phương thức adapter.\n3. Khi nhận được lệnh gọi, adapter sẽ chuyển yêu cầu đến đối tượng thứ hai, nhưng theo một định dạng và trật tự mà đối tượng thứ hai có thể hiểu được.\n\nĐôi khi, ta có thể tạo adapter hai chiều để chuyển đổi cuộc gọi theo cả hai hướng.\n\n![solution](./assets/solution.png)\n\nTrở về với ứng dụng thị trường chứng khoán, để giải quyết tình trạng định dạng không tương thích, ta sẽ tạo một adapter XML-to-JSON cho tất cả các lớp trong thư viện phân tích để code bạn làm việc trực tiếp. Sau đó bạn điều chỉnh code của bạn làm việc với thư viện thông qua adapter.\n\nKhi adapter nhận được một lệnh gọi, nó sẽ dịch dữ liệu XML sang cấu trúc JSON và chuyển hướng cuộc gọi đến các phương thức thích hợp của đối tượng phân tích đã được bọc.\n\n## 🚗 Thế Giới Thực\n\n![analogy](./assets/analogy.png)\n\nKhi bạn đi du lịch từ Mỹ đến châu Âu lần đầu tiên, bạn có thể sẽ sốc khi sạc laptop của mình. Vì chuẩn ổ cắm và nguồn điện của các quốc gia khác nhau sẽ khác nhau. Đó là lý do tại sao phích cắm Hoa Kỳ sẽ không phù hợp với ổ cắm ở Đức. Vấn đề có thể được giải quyết bằng cách sử dụng bộ chuyển đổi có ổ cắm kiểu Hoa Kỳ và phích cắm kiểu châu Âu.\n\n## 🏢 Cấu trúc\n\n### Đối tượng adapter\n\nViệc triển khai này sử dụng nguyên tắc cấu thành đối tượng: adapter triển khai interface của một đối tượng và bọc một đối tượng khác. Nó có thể triển khai trên mọi ngôn ngữ lập trình.\n\n![object_structure](./assets/structure1.png)\n\n1. **Client** là lớp bao gồm các code logic hiện có của chương trình.\n2. **Client Interface** mô tả giao thức mà các lớp khác phải theo để có thể cộng tác với code client.\n3. **Service** là một vài lớp hữu ích (thường là bên thứ 3 hoặc kế thừa). Client không thể sử dụng trực tiếp vì không tương thích interface.\n4. **Adapter** là lớp có thể làm việc với cả client và service. Nó triển khai client interface trong khi bọc đối tượng service. Adapter nhận lệnh gọi từ client thông qua adapter interface và dịch nó, sau đó nó gọi lại đối tượng service được bọc dưới định dạnh service có thể hiểu được.\n5. Code client không cần phải ghép với lớp adapter cụ thể miễn là nó làm việc với adapter thông qua client interface. Nhờ điều đó, bạn có thể thêm kiểu adapter mới vào chương trình mà không ảnh hưởng đến code client. Điều này có thể hữu ích khi interface của lớp service có thay đổi: bạn có thể tạo lớp adapter mới mà không cần thay đổi code client.\n\n### Lớp adapter\n\nTriển khai này sử dụng kế thừa: adapter kế thừa interface từ cả hai đối tượng vào cùng thời điểm. Lưu ý là cách tiếp cận này chỉ triển khai trên các ngôn ngữ lập trình hỗ trợ đa kế thừa, như C++.\n\n![class_structure](./assets/structure2.png)\n\n**Lớp Adapter** không cần bọc bất kỳ đối tượng nào vì nó sẽ kế thừa hành vi từ cả client và service. Sự chuyển đối diễn ra bên trong phương thức override. Adapter kết quả có thể sử dụng \nthay thể cho một lớp client hiện có.\n\n## 👨‍💻 Mã giả\n\nVí dụ cho pattern Adapter sẽ dựa trên câu thành ngữ: \"chốt gỗ vuông trong lỗ tròn\"(Square pegs in round holes).\n\n![pseudocode](./assets/pseudocode.png)\n\nAdapter giả vờ là một chốt tròn(round peg), có bán kính bằng một nửa đường chéo của hình vuông (nói cách khác, là bán kính của hình tròn nhỏ nhất có thể chứa vừa hình vuông).\n\n```c\n// Giả sử bạn có hai lớp với interface tương thích:\n// RoundHole và RoundPeg.\nclass RoundHole is\n    constructor RoundHole(radius) { ... }\n\n    method getRadius() is\n        // Trả về bán kính của lỗ.\n\n    method fits(peg: RoundPeg) is\n        return this.getRadius() >= peg.getRadius()\n\nclass RoundPeg is\n    constructor RoundPeg(radius) { ... }\n\n    method getRadius() is\n        // Trả về bán kính của chốt.\n\n\n// Nhưng có một lớp không tương thích là: SquarePeg.\nclass SquarePeg is\n    constructor SquarePeg(width) { ... }\n\n    method getWidth() is\n        // Trả về độ dài của chốt.\n\n\n// Lớp adapter giúp bạn cho chốt vuông vào vừa lỗ tròn.\n// Nó mở rộng lớp RoundPeg để giúp đối tượng adapter hành\n// động như một chốt tròn.\nclass SquarePegAdapter extends RoundPeg is\n    // Thực tế, adapter bao gồm một thực thể của\n    // lớp SquarePeg\n    private field peg: SquarePeg\n\n    constructor SquarePegAdapter(peg: SquarePeg) is\n        this.peg = peg\n\n    method getRadius() is\n        // Apdater giả vờ là một chốt tròn với bán kính\n        // vừa với chốt vuông mà adapter thực sự bọc.\n        return peg.getWidth() * Math.sqrt(2) / 2\n\n\n// Đâu đó trong code client.\nhole = new RoundHole(5)\nrpeg = new RoundPeg(5)\nhole.fits(rpeg) // true\n\nsmall_sqpeg = new SquarePeg(5)\nlarge_sqpeg = new SquarePeg(10)\nhole.fits(small_sqpeg) // điều này sẽ không biên dịch (các loại không tương thích)\n\nsmall_sqpeg_adapter = new SquarePegAdapter(small_sqpeg)\nlarge_sqpeg_adapter = new SquarePegAdapter(large_sqpeg)\nhole.fits(small_sqpeg_adapter) // true\nhole.fits(large_sqpeg_adapter) // false\n```\n\n## 💡 Ứng dụng\n\n**🐞 Sử dụng lớp Adapter khi bạn muốn dùng một số lớp hiện có, nhưng interface của nó không tương thích với code của bạn**\n\n⚡ Adapter cho phép bạn tạo một lớp trung gian đóng vai trò như một trình dịch giữa code của bạn và lớp kế thừa, lớp của bên thứ 3 hoặc bất kỳ lớp nào khác có interface không tương thích.\n\n**🐞 Sử dụng Adapter khi bạn muốn sử dụng lại các lớp con hiện có nhưng thiếu một số hàm chung không thể thêm vào lớp cha**\n\n⚡ Bạn có thể mở rộng từng lớp con và đưa hàm còn thiếu vào các lớp con mới. Tuy nhiên, bạn sẽ cần phải sao chép code trên tất cả các lớp mới này, điều này khá tệ.\n\nGiải pháp tốt hơn là đưa các hàm bị thiếu vào lớp adapter. Sau khi bạn bọc đối tượng với chức năng thiếu trong adapter, thu được các tính năng cần thiết một cách linh động. Để hoạt động, các lớp đích phải có interface chung và trường của adapter phải theo interface. Các tiếp cận này có phần tương đồng pattern Decorator.\n\n## 📋 Triển khai\n\n1. Chắc chắn rằng bạn có ít nhất hai lớp với interface không tương thích:\n    - Lớp service, bạn không thể thay đổi (như bên thứ 3 hay kế thừa)\n    - Một hoặc nhiều lớp client sẽ có ích khi sử dụng lớp service.\n\n2. Khai báo client interface và mô tả cách client giao tiếp với service.\n\n3. Tạo lớp adapter theo client interface. Tạm thời để trống tất cả phương thức.\n\n4. Thêm trường vào lớp adapter để lưu trữ tham chiếu đến đối tượng service. Cách phổ biến là tạo trường này thông qua hàm khởi tạo, nhưng đôi khi truyền nó cho adapter khi gọi các phương thức của nó sẽ thuận tiện hơn.\n\n5. Triển khai tất cả phương thức của client interface trong lớp adapter. Adapter nên uỷ thác phần lớp phần lớn công việc thực cho đối tượng service, và chỉ xử lý interface hoặc chuyển đổi định dạng dữ liệu.\n\n6. Client nên sử dụng adapter thông qua client interface. Điều này giúp bạn thay đổi hoặc mở rộng adapter mà không ảnh hưởng đến code client.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ *Single Responsibility Principle* Bạn có thể tách interface hoặc code chuyển đổi dữ liệu khỏi logic nghiệp vụ chính của chương trình.\n\n✔️ *Open/Closed Principle* Bạn có thể giới thiệu các loại adapter mới vào chương trình mà không ảnh hưởng code client hiện có, miễn là chúng hoạt động với adapter thông qua client interface.\n\n### Nhược điểm\n\n❌ Độ phức tạp tổng thể của code tăng lên vì bạn cần giới thiệu một tập hợp các interface và lớp mới. Đôi khi, việc thay đổi lớp service sao cho phù hợp với phần còn lại của code của bạn sẽ đơn giản hơn.\n\n## 🔁 Quan hệ với các pattern khác\n\n**Bridge** thường được thiết kế từ trước, cho phép bạn phát triển các phần của ứng dụng một cách độc lập với nhau. Mặt khác, **Adapter** thường được sử dụng với một ứng dụng hiện có để  một số lớp không tương thích hoạt động với nhau.\n\n**Adapter** thay đổi interface của một đối tượng hiện có, trong khi **Decorator** nâng cao một đối tượng mà không thay đổi interface của nó. Ngoài ra, **Decorator** hỗ trợ thành phần đệ quy, điều này không thể thực hiện được khi bạn sử dụng **Adapter**.\n\n**Adapter** cung cấp một interface khác cho đối tượng được bọc, **Proxy** cung cấp cho nó một interface tương tự và **Decorator** cung cấp cho nó một interface nâng cao.\n\n**Facade** định nghĩa một interface mới cho các đối tượng hiện có, trong khi **Adapter** cố gắng làm cho interface hiện có có thể sử dụng được. **Adapter** thường chỉ bọc một đối tượng, trong khi **Facade** hoạt động với toàn bộ hệ thống con của các đối tượng.\n\n**Bridge**, **State**, **Strategy** (và ở một mức độ nào đó là **Adapter**) có cấu trúc rất giống nhau. Thật vậy, tất cả các pattern này đều dựa trên nguyên tắc là ủy thác công việc cho các đối tượng khác. Tuy nhiên, chúng giải quyết các vấn đề khác nhau. Một pattern không chỉ là một công thức để cấu trúc code của bạn theo một cách cụ thể. Nó còn có thể giao tiếp với các nhà phát triển khác về vấn đề mà pattern giải quyết.\n\n# Nguồn\n\n[**refactoring**](https://refactoring.guru/design-patterns/adapter)"
  },
  {
    "path": "structural-pattern/bridge/README.md",
    "content": "# Bridge\n\n## 📜 Mục đích\n\n**Bridge** là design pattern thuộc nhóm structural giúp bạn tách một lớp khổng lồ hoặc một tập hợp lớp có quan hệ gần gũi với nhau thành hai hệ thống phân cấp lớp riêng biệt là - abstraction(trừu tượng) và implementation(triển khai) - có thể phát triển độc lập với nhau.\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nGiả sử bạn có một lớp hình học `Shape` với các lớp con: `Circle` và `Square`. Bạn muốn mở rộng hệ thống phân cấp lớp này để kết hợp với màu sắc, kế hoạch của bạn là tạo lớp con `Red` và `Blue`. Tuy nhiên, vì bạn đã có hai lớp con rồi, nên bạn sẽ cần tạo bốn lớp kết hợp, vd như `BlueCircle` và `RedSquare`.\n\n![problem](./assets/problem.png)\n\n*Số lượng kết hợp tăng lên theo tiến trình hình học.*\n\nThêm một hình dạng mới hay màu sắc vào hệ thống phân cấp sẽ làm nó phát triển theo cấp số mũ. Ví dụ, thêm hình tam giác vào bạn sẽ cần thêm hai lớp con cho mỗi màu, sau đó nếu thêm một màu vàng vào sẽ lại cần thêm ba lớp con cho từng hình dạng. Càng thêm nhiều thì mọi thứ càng tệ đi.\n\n## 😊 Giải pháp\n\nVấn đề này xảy ra khi ta cố gắng mở rộng lớp `Shape` thành hai phần độc lập là: hình dạng và màu sắc. Đây là vấn đề rất phổ biến với kế thừa lớp.\n\nPattern Bridge giải quyết vấn đề này bằng cách chuyển từ kế thừa sang cấu thành đối tượng. Có nghĩa là bạn sẽ trích xuất một phần trong lớp gốc thành các hệ thống phân cấp lớp riêng biệt, thế nên lúc này lớp gốc của bạn sẽ tham chiếu đến đối tượng của hệ thống phân cấp mới, thay vì chứa tất cả trạng thái và hành vi của nó trong một lớp.\n\n![solution](./assets/solution.png)\n\n*Bạn có thể ngăn chặn sự bùng nổ của hệ thống phân cấp lớp bằng cách chuyển đổi nó thành một số hệ thống phân cấp có quan hệ*\n\nVới cách tiếp cận này ta sẽ trích xuất code liên quan đến màu sắc thành một lớp riêng với hai lớp con: `Red` và `Blue`. Lớp `Shape` sẽ lấy trường tham chiếu đến một trong những đối tượng màu sắc. Bây giờ `Shape` có thể uỷ thác mọi công việc liên quan đến màu sắc cho đối tượng `color` được liên kết. Tham chiếu này hoạt động như một cây cầu (bridge) giữa lớp `Shape` và `Color`. Từ giờ khi thêm màu mới sẽ không cần thay đổi hệ thống phân cấp lớp `Shape` và ngược lại.\n\n### Abstraction và Implementation\n\nQuyền sách [GoF](https://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional-ebook/dp/B000SEIBB8) giới thiệu thuật ngữ *Abstraction* và *Implementation* như là một phần trong định nghĩa Bridge. Theo quan điểm cá nhân thì thuật ngữ này khá hàn lâm và làm cho pattern trông phức tạp hơn. Sau khi xem ví dụ đơn giản hơn với màu sắc và hình dạng, ta có thể diễn giải lại nó như sau:\n\n**Abstraction** (còn gọi là interface) là một lớp(tầng) điều khiển cấp cao cho một vài thực thể. Lớp này không thực hiện bất cứ công việc gì trong nó. Nó uỷ thác công việc cho lớp **implementation** (còn gọi là platform). \n\nLưu ý, ở đây ta không nói về *interface* hay lớp trừu tượng trong ngôn ngữ lập trình của bạn. Đây là hai thứ hoàn toàn khác nhau.\n\nVí dụ một ứng dụng thực tế, abstraction có thể biểu diễn bằng giao diện đồ hoạ người dùng (GUI), và implementation có thể là những đoạn code hệ điều hành cơ bản (API), nơi lớp GUI gọi để phản hồi tương tác người dùng.\n\nKhi bạn mở rộng ứng dụng theo hai hướng độc lập: \n- Có nhiều GUI khác nhau (vd như giao diện cho người dùng hay admin).\n- Hỗ trợ nhiều API khác nhau(ví dụ như chạy ứng dụng dưới các hệ điều hành Windows, Linux, MacOS)\n\nTrong trường hợp xấu nhất, ứng dụng này có thể trông giống như một tô mì spaghetti khổng lồ, nơi hàng trăm điều kiện kết nối các loại GUI khác nhau với các API khác nhau trên toàn bộ code.\n\n![abstraction](./assets/abstraction.png)\n\nBạn có thể làm cho mọi thứ ổn định hơn bằng cách trích xuất code liên quan đến interface-platform thành các lớp riêng biệt. Tuy nhiên, sẽ có rất nhiều lớp trong đấy. Hệ thống phân cấp lớp sẽ phát triển theo cấp số mũ khi thêm một GUI hay hỗ trợ một API khác, vì sẽ yêu cầu tạo thêm nhiều và nhiều hơn các lớp nữa.\n\nVấn đề này sẽ được giải quyết bằng Bridge, khi ta chia các lớp thành hai hệ thống phân cấp lớp: \n- Abstraction: lớp GUI của ứng dụng.\n- Implementation: các API của hệ điều hành.\n\n![implement](./assets/implement.png)\n\nĐối tượng abstraction điều khiển vẻ ngoài của ứng dụng, uỷ thác các công việc thực cho đối tượng implementation được liên kết. Sự khác nhau của các implementation có thể hoán đổi với nhau miễn là nó theo một interface chung, cho phép cùng một GUI chạy trên cả Windows và Linux.\n\nKết quả là, bạn có thể thay đổi lớp GUI mà không cần đụng đến lớp API liên quan. Hơn thế nữa khi thêm hỗ trợ cho một hệ điều hành khác chỉ yêu cầu tạo lớp con cho hệ thống phân cấp implementation.\n\n## 🏢 Cấu trúc\n\n![structure](./assets/structure.png)\n\n1. **Abstraction** cung cấp logic điều khiển cấp cao. Nó dựa vào các đối tượng implementation để thực hiện các công việc ở cấp thấp hơn.\n2. **Implementation** khai bao interface chung cho tất cả concrete implementations. Abstraction chỉ giao tiếp với đối tượng implementation thông qua phương thức đã khai báo ở đây.\n3. **Concrete implementation** bao gồm code platform cụ thể.\n4. **Refined Abstractions** cung cấp biến thể cho logic điều khiển. Giống như lớp cha, nó làm việc với implementation thông qua interface implementation chung.\n5. Thông thường, **Client** chỉ quan tâm đến việc làm việc với abstraction. Tuy nhiên, nhiệm vụ của client là liên kết đối tượng abstraction với một trong các đối tượng implementation.\n\n## 👨‍💻 Mã giả\n\nVí dụ minh hoạ cách Bridge phân chia khối code của ứng dụng để quản lý thiết bị và điều khiển từ xa. Lớp `Device` hoạt động như implementation, trong khi `Remote` hoạt động như abstraction.\n\n![pseudocode](./assets/pseudocode.png)\n\nLớp cơ sở của `Remote` khai báo trường tham chiếu liên kết với đối tượng `Device`. Tất cả điều khiển làm việc với thiết bị thông qua interface `Device` chung, nó giúp cùng một điều khiển hỗ trợ nhiều loại thiết bị.\n\nBạn có thể phát triển lớp `Remote` độc lập với lớp `Device`. Tất cả những gì cần chỉ là tạo một lớp con remote mới. Ví dụ, điều khiển từ xa đơn gian chỉ có hai nút, bạn có thể mở rộng nó với các tính năng như pin dự phòng hay cảm ứng.\n\nCode client liên kết với remote mong muốn và đối tượng thiết bị cụ thể thông qua hàm khởi tạo của remote.\n\n```c\n// \"Abstraction\" định nghĩa interface cho \"control\" của\n// hai hệ thống phân cấp lớp. Nó duy trì một liên kết đến đối \n// tượng của hệ thống phân cấp \"implementation\" và uỷ thác\n// các công việc thực cho đối tượng đó.\nclass RemoteControl is\n    protected field device: Device\n    constructor RemoteControl(device: Device) is\n        this.device = device\n    method togglePower() is\n        if (device.isEnabled()) then\n            device.disable()\n        else\n            device.enable()\n    method volumeDown() is\n        device.setVolume(device.getVolume() - 10)\n    method volumeUp() is\n        device.setVolume(device.getVolume() + 10)\n    method channelDown() is\n        device.setChannel(device.getChannel() - 1)\n    method channelUp() is\n        device.setChannel(device.getChannel() + 1)\n\n\n// Bạn có thể mở rộng lớp từ hệ thống phân cấp abstraction\n// độc lập với lớp device.\nclass AdvancedRemoteControl extends RemoteControl is\n    method mute() is\n        device.setVolume(0)\n\n\n// Interface \"implementation\" khai báo phương thức chung cho \n// tất cả lớp implementation cụ thể. Nó không cần ứng với\n// interface abstraction. Sự thật là hai interface có thể\n// khác nhau toàn bộ. Tiêu biểu như interface implementation\n// chỉ cung cấp toán tử nguyên thuỷ, trong khi abstraction\n// khai báo các toán tử cấp cao dựa trên các nguyên thuỷ đó.\ninterface Device is\n    method isEnabled()\n    method enable()\n    method disable()\n    method getVolume()\n    method setVolume(percent)\n    method getChannel()\n    method setChannel(channel)\n\n\n// Tất cả thiết bị theo cùng một interface.\nclass Tv implements Device is\n    // ...\n\nclass Radio implements Device is\n    // ...\n\n\n// Đâu đó trong code client.\ntv = new Tv()\nremote = new RemoteControl(tv)\nremote.togglePower()\n\nradio = new Radio()\nremote = new AdvancedRemoteControl(radio)\n```\n\n## 💡 Ứng dụng\n\n**🐞 Sử dụng Bridge khi bạn muốn phân chia và tổ chức khối lớp của bạn thành các phần biến thể cho một số chức năng**\n\n⚡ Ví dụ như khi bạn làm việc với server của các cơ sở dữ liệu khác nhau. Lớp có thể trở nên quá to và khó khăn để tìm hiểu cách nó hoạt động, và khó hơn nữa để thay đổi nó. Các thay đổi với một biến thể của chức năng có thể yêu cầu thay đổi lên toàn bộ lớp, kết quả có thể tạo ra lỗi hoặc các tác dụng phụ nghiệm trọng.\n\nBridge giúp bạn tách khối lớp thành các hệ thống phân cấp lớp. Sau đó bạn có thể thay đổi lớp của một hệ thống phân cấp độc lập với các lớp khác. Cách tiếp cận này giúp code dễ bảo trì và tối thiểu nguy cơ code đang có bị ảnh hưởng.\n\n**🐞 Sử dụng Bridge nếu bạn muốn mở rộng các lớp độc lập với nhau**\n\n⚡ Bridge giúp bạn trích xuất một hệ thống phân cấp lớp riêng biệt cho từng phần. Lớp ban đầu ủy thác công việc liên quan cho các đối tượng thuộc các phân cấp đó thay vì tự làm mọi thứ. \n\n**🐞 Sử dụng Bridge nếu bạn cần chuyển đổi các implementation trong thời gian chạy**\n\n⚡ Mặc dù là tùy chọn, nhưng Bridge cho phép bạn thay thế đối tượng implementation bên trong phần abstraction. Nó dễ dàng như việc gán một giá trị mới cho một trường.\n\nNhân tiện, mục cuối cùng này là lý do chính khiến nhiều người nhầm lẫn giữa pattern Bridge với pattern Strategy. Hãy nhớ rằng một pattern không chỉ là cách để cấu trúc các lớp của bạn. Nó cũng có thể là một ý tưởng cho một vấn đề đang được giải quyết.\n\n## 📋 Triển khai\n\n1. Xác định các phần độc lập trong lớp của bạn. Các khái niệm độc lập có thể là: abstraction/platform, domain/infrastructure, front-end/back-end, or interface/implementation.\n\n2. Xem các hoạt động mà client cần và định nghĩa chúng ở lớp abstraction cơ sở.\n3. Xác định các hoạt động có sẵn trên tất cả nền tảng. Khai báo những cái mà abstraction cần trong interface implementation chung.\n4. Với tất cả nền tảng trong miền của bạn, tạo các lớp concrete implementation, đảm bảo rằng tất cả chúng theo interface implementation.\n5. Trong lớp abstraction, thêm trường tham chiếu cho kiểu implementation. Abstraction uỷ quyền hầu hất công việc cho đối tượng implementation có liên kết với trường đó.\n6. Nếu bạn có các logic cấp cao khác nhau, tạo refined abstraction cho từng biến thể được mở rộng bằng lớp abstraction cơ sở.\n7. Code client nên truyền đối tượng implementation vào hàm khởi tạo abstraction để liên kết một đối tượng này với đối tượng kia. Sau đó, client có thể quên đi implementation và chỉ làm việc với đối tượng abstraction.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ Bạn có thể tạo các lớp và ứng dụng độc lập với nền tảng.\n\n✔️ Code client hoạt động với abstraction cấp cao. Nó không hiển thị với các nền tảng chi tiết.\n\n✔️ *Open/Closed Principle* Bạn có thể giới thiệu abstraction và implementation mới một cách độc lập với nhau.\n\n✔️ *Single Responsibility Principle* Bạn có thể tập trung vào logic cấp cao trong phần abstraction và chi tiết nền tảng trong quá trình implementation. \n\n### Nhược điểm\n\n❌ Bạn có thể làm cho code phức tạp hơn bằng cách áp dụng pattern cho một lớp có tính dính kết cao.\n\n## 🔁 Quan hệ với các pattern khác\n\n**Bridge** thường được thiết kế từ trước, cho phép bạn phát triển các phần của ứng dụng một cách độc lập với nhau. Mặt khác, **Adapter** thường được sử dụng với một ứng dụng hiện có để  một số lớp không tương thích hoạt động với nhau.\n\n**Bridge**, **State**, **Strategy** (và ở một mức độ nào đó là **Adapter**) có cấu trúc rất giống nhau. Thật vậy, tất cả các pattern này đều dựa trên nguyên tắc là ủy thác công việc cho các đối tượng khác. Tuy nhiên, chúng giải quyết các vấn đề khác nhau. Một pattern không chỉ là một công thức để cấu trúc code của bạn theo một cách cụ thể. Nó còn có thể giao tiếp với các nhà phát triển khác về vấn đề mà pattern giải quyết.\n\nBạn có thể sử dụng **Abstract Factory** cùng với **Bridge**. Việc ghép nối này rất hữu ích khi một số abstract được xác định bởi **Bridge** chỉ có thể hoạt động với các implementation cụ thể. Trong trường hợp này, **Abstract Factory** có thể đóng gói các quan hệ này và ẩn sự phức tạp khỏi code client.\n\nBạn có thể kết hợp **Builder** với **Bridge**: lớp director đóng vai trò abstraction, trong khi các builder khác đóng vai trò implementation.\n\n# Nguồn\n\n[**refactoring**](https://refactoring.guru/design-patterns/bridge)"
  },
  {
    "path": "structural-pattern/composite/README.md",
    "content": "# Composite\n\n## 📜 Mục đích\n\n**Composite** là một design pattern thuộc nhóm structural cho phép bạn sắp xếp các đối tượng thành cấu trúc cây và sau đó làm việc với các cấu trúc này như thể chúng là các đối tượng riêng lẻ.\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nSử dụng pattern Composite chỉ hợp lý khi mô hình cốt lõi của ứng dụng bạn có thể biểu diễn dạng cây.\n\nVí dụ, tưởng tượng bạn có hai loại đối tượng: `Product` và `Box`. `Box` có thể bao gồm nhiều `Product` và một số lượng `Box` nhỏ hơn.Các box nhỏ hơn đó có thể bao gồm `Product` hoặc `Box` nhỏ hơn khác nữa.\n\nKhi bạn định tạo một hệ thống đặt hàng sử dụng các lớp đấy. Đơn hàng (`Order`) có thể bao gồm một sản phẩm đơn giản không bị bọc, cũng có thể là một cái hộp đựng sản phẩm và các hộp khác.\nVậy làm thế nào để bạn tính tổng giá trị của đơn hàng?\n\n![problem](./assets/problem.png)\n\nBạn có thể giải quyết trực tiếp: mở tất cả các hộp và cộng tất cả các sản phẩm lại với nhau. Đây là cách giải quyết trong đời sống thực, nhưng trong các chương trình máy tính nó không đơn giản như vậy. Bạn phải biết lớp của `Product` và `Box` mà bạn cần, cấp độ lồng nhau của hộp và các chi tiết khó hiểu khác. Tất cả điều này khiến cách tiếp cận trực tiếp trở nên khó khăn thậm chí là không thể.\n\n## 😊 Giải pháp\n\nPattern Composite cho bạn ý tưởng là làm việc với `Product` và `Box` qua một interface chung, interface này đã khai báo phương thức tính tổng giá tiền.\n\nVậy phương thức này vận hành thế nào ? Với sản phẩm, rất đơn giản để trả về giá tiền của sản phẩm đó. Với hộp, nó sẽ đi qua tất cả thành phần trong hộp, lấy giá tiền và trả về tổng giá cho hộp. Nếu một thành phần là hộp nhỏ hơn, hộp đấy sẽ bất đầu đi qua các thành phần trong đó, cho đến tính xong giá của tất cả thành phần bên trong nó. Một hộp thậm chí có thể thêm một số chi phí bổ sung vào giá cuối cùng, chẳng hạn như chi phí đóng gói. \n\n![solution](./assets/solution.png)\n\n*Composite cho phép bạn chạy đệ quy trên tất cả các thành phần của cây đối tượng*\n\nLợi ích tuyệt vời của giải pháp này là bạn không cần quan tâm lớp cụ thể của đối tượng cấu thành cây. Bạn không cần biết đối tượng đó là một sản phẩm đơn giản hay một hộp phức tạp. Bạn có thể xử lý như nhau thông qua interface chung. Khi bạn gọi phương thức, đối tượng sẽ tự động chuyển yêu cầu xuống phía dưới cây.\n\n## 🚗 Thế Giới Thực\n\n![analogy](./assets/analogy.png)\n\nQuân đội của hầu hết quốc gia đều có cấu trúc như cây phân cấp. Quân đội sẽ bao gồm các sư đoàn: các sư đoàn bao gồm các trung đoàn, các trung đoàn bao gồm các tiểu đoàn, các tiểu đoàn lại bao gồm các đại đội, trung đội, tiểu đội. Các mệnh lệnh được đưa ra ở trên cùng của hệ thống phân cấp sẽ được truyền xuống từng cấp độ cho đến khi mọi người lính biết những gì cần phải làm.\n\n## 🏢 Cấu trúc\n\n![structure](./assets/structure.png)\n\n1. **Component** là interface khai báo hoạt động chung cho cả phần tử phức tạp và đơn giản của cây.\n2. **Leaf** là phần tử cơ bản của cây, không bao gồm bất kỳ phần tử con nào. Thông thường, các thành phần leaf thực hiện hầu hết các công việc thực, vì chúng không có bất kỳ ai để ủy thác.\n3. **Container** (hoặc composite-phức hợp) là một phần tử có các phần tử con là leaf hoặc các container khác. Một container không biết các lớp cụ thể của các lớp con của nó. Nó chỉ hoạt động với tất cả các phần tử con thông qua interface component.\n4. **Client** làm việc với tất cả các phần tử thông qua interface component. Do đó, client có thể làm việc theo cùng một cách với cả các phần tử đơn giản hoặc phức tạp của cây.\n\n## 👨‍💻 Mã giả\n\nỞ ví dụ này, Composite giúp bạn triển khai ngăn xếp của các dạng hình học ở trình thiết kế đồ hoạ.\n\n![pseudocode](./assets/pseudocode.png)\n\nLớp `CompoundGraphic` là một container có thể bao gồm bất kỳ số lượng hình dạng con nào, bao gồm cả các container khác. Một hình dạng container có cùng phương thức với hình dạng đơn giản. Tuy nhiên, thay vì thực hiện điều gì đó trên chính nó, thì nó chuyển yêu cầu xuống tất cả con của nó và tính tổng bằng đệ quy.\n\nCode client làm việc với tất cả hình dạng qua interface chung duy nhất cho tất cả lớp hình dạng. Do đó, client không biết nó đang làm việc với dạng đơn giản hay phức hợp. Nó có thể làm việc với các đối tượng có cấu trúc phức tạp mà không cần ghép với lớp cụ thể tạo nên cấu trúc đấy.\n\n```c\n// Interface component khai báo các hoạt động chung cho\n// cả đối tượng đơn giản và phức tạp của cây.\ninterface Graphic is\n    method move(x, y)\n    method draw()\n\n// Lớp leaf biểu diễn đối tượng cuối cùng của cây. Đối tượng\n// leaf không thể có bất kỳ đối tượng con nào. Thông thường\n// leaf của một đối tượng là nơi làm việc thực, trong khi các\n// đối tượng container uỷ thác cho con của nó.\nclass Dot implements Graphic is\n    field x, y\n\n    constructor Dot(x, y) { ... }\n\n    method move(x, y) is\n        this.x += x, this.y += y\n\n    method draw() is\n        // Vẽ chấm X và Y.\n\n// Tất cả lớp component có thể mở rộng các component khác.\nclass Circle extends Dot is\n    field radius\n\n    constructor Circle(x, y, radius) { ... }\n\n    method draw() is\n        // Vẽ hình tròn tại X và Y với bán kính R.\n\n// Lớp container biểu diễn component phức tạp có thể có con.\n// Đối tượng container thường uỷ thác công việc thực cho\n// con của nó và tính kết quả tổng.\nclass CompoundGraphic implements Graphic is\n    field children: array of Graphic\n\n    // Đối tượng container có thể thêm hoặc xoá component khác\n    // (cả đơn giản và phức tạp) vào hoặc khỏi danh sách con \n    // của nó.\n    method add(child: Graphic) is\n        // Thêm con vào mảng danh sách con.\n\n    method remove(child: Graphic) is\n        // Xoá con khỏi mảng danh sách con.\n\n    method move(x, y) is\n        foreach (child in children) do\n            child.move(x, y)\n\n    // Một container thực hiện logic chính của nó theo một cách cụ thể.\n    // Nó duyệt đệ quy qua tất cả các con của nó, thu thập và tổng hợp\n    // kết quả của chúng. Vì các con của container chuyển các lệnh gọi\n    // này cho các con của chính chúng và tiếp tục như thế, nên kết quả\n    // cuối cùng là toàn bộ cây đối tượng được duyệt qua.\n    method draw() is\n        // 1. Với mỗi component con:\n        //      - Vẽ component\n        //      - Cập nhật giới hạn hình chữ nhật.\n        // 2. Vẽ một hình chữ nhật đứt nét bằng cách \n        // sử dụng các tọa độ giới hạn.\n\n\n// Code client làm việc với tất cả component thông qua\n// interface cơ sở. Với cách này code client có thể \n// hỗ trợ leaf đơn giản cũng như các container phức tạp.\nclass ImageEditor is\n    field all: CompoundGraphic\n\n    method load() is\n        all = new CompoundGraphic()\n        all.add(new Dot(1, 2))\n        all.add(new Circle(5, 3, 10))\n        // ...\n\n    // Kết hợp các component đã chọn thành một \n    // container phức tạp.\n    method groupSelected(components: array of Graphic) is\n        group = new CompoundGraphic()\n        foreach (component in components) do\n            group.add(component)\n            all.remove(component)\n        all.add(group)\n        // Tất cả component đều được vẽ.\n        all.draw()\n```\n\n## 💡 Ứng dụng\n\n**🐞 Sử dụng Composite khi bạn muốn triển khai đối tượng có cấu trúc giống cây**\n\n⚡ Pattern Composite cung cấp cho bạn hai kiểu phần tử đơn giản có interface chung: leaf đơn giản và container(composite) phức tạp. Container có thể bao gồm leaf và container khác. Nó giúp bạn khởi tạo các đối tượng có cấu trúc đệ quy lồng nhau giống cây.\n\n**🐞 Sử dụng Composite khi bạn muốn code client xử lý đồng nhất cả phần tử đơn giản và phức tạp**\n\n⚡ Tất cả phần tử được xác định với pattern Composite chia sẻ chung interface. Sử dụng interface này, code client không cần quan tâm đến lớp cụ thể mà đối tượng làm việc.\n\n## 📋 Triển khai\n\n1. Đảm bảo rằng mô hình cốt lõi của ứng dụng có thể biểu diễn cấu trúc cây. Cố gắng chia nhỏ thành các phần tử đơn giản và container. Nhớ là container có thể bao gồm cả phần tử đơn giản và container khác.\n\n2. Khai báo interface component với danh sách phương thức hợp lý cho cả component đơn giản và phức tạp.\n\n3. Tạo lớp leaf để biểu diễn phần tử đơn giản. Chương trình có thể có nhiều lớp leaf khác nhau.\n\n4. Tại lớp container biểu diễn phần tử phức tạp. Trong lớp này, cung cấp mảng để lưu trữ tham chiếu đến phần tử. Mảng có thể lưu cả leaf và container khác, chắc chắn rằng nó được khai báo với kiểu interface component.\nTrong khi triển khai phương thức của interface component, hãy nhớ container thường uỷ thác phần lớn công việc cho phần tử con.\n\n5. Cuối cùng định nghĩa phương thức thêm và xoá phần tử con ở container. Hãy ghi nhớ rằng các hoạt động có thể khai báo ở interface component. Điều này sẽ vi phạm *Nguyên tắc Phân tách Interface* vì phương thức sẽ trống trong lớp leaf. Tuy nhiên, client sẽ xử lý tất cả phần tử như nhau, khi cấu thành cây.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ Bạn có thể làm việc với cấu trúc cây phức tạp thuật tiện hơn: sử dụng kiểu đa hình và đệ quy.\n\n✔️ *Open/Closed Principle* Bạn có thể thêm một kiểu phần tử mới vào ứng dụng mà không ảnh hưởng đến code hiện có, chỉ hiệu quả với đối tượng cây.\n\n### Nhược điểm\n\n❌ Có thể khó cung cấp một interface chung cho các lớp có chức năng khác nhau quá nhiều. Trong một số trường hợp nhất định, bạn cần phải tổng quát hóa quá mức interface component, khiến nó khó hiểu hơn.\n\n## 🔁 Quan hệ với các pattern khác\n\nBạn có thể sử dụng **Builder** khi tạo các cây **Composite** phức tạp vì bạn có thể lập trình các bước xây dựng của nó để hoạt động bằng đệ quy.\n\n**Chain of Responsibility** thường được sử dụng cùng với **Composite**. Trong trường hợp này, khi một thành phần leaf nhận được một yêu cầu, nó có thể chuyển nó qua chuỗi của tất cả các thành phần mẹ xuống gốc của cây đối tượng.\n\nBạn có thể sử dụng **Iterator** để duyệt qua các cây **Composite**.\n\nBạn có thể sử dụng **Visitor** để thực hiện một hoạt động trên toàn bộ cây **Composite**.\n\nBạn có thể triển khai các nút leaf chia sẻ của cây **Composite** dưới dạng **Flyweights** để tiết kiệm dung lượng RAM.\n\n**Composite** và **Decorator** có các sơ đồ cấu trúc tương tự vì cả hai đều dựa vào thành phần đệ quy để tổ chức một số lượng các đối tượng kết thúc mở.\n\n- **Decorator** giống như **Composite** nhưng chỉ có một thành phần con. Sự khác biệt đáng kể khác là **Decorator** thêm các trách nhiệm bổ sung cho đối tượng được bao bọc, trong khi **Composite** chỉ \"tính tổng\" các kết quả con của nó.\n\n- Tuy nhiên, các pattern cũng có thể hợp tác: bạn có thể sử dụng **Decorator** để mở rộng hành vi của một đối tượng cụ thể trong cây **Composite**.\n\nCác thiết kế sử dụng nhiều **Composite** và **Decorator** thường có thể được hưởng lợi từ việc sử dụng Prototype. Áp dụng pattern cho phép bạn sao chép các cấu trúc phức tạp thay vì xây dựng lại chúng từ đầu.\n\n# Nguồn \n\n[**refactoring**](https://refactoring.guru/design-patterns/composite)"
  },
  {
    "path": "structural-pattern/decorator/README.md",
    "content": "# Decorator\n\n## 📜 Mục đích\n\n**Decorator** là một design pattern thuộc nhóm structural giúp bạn thêm một hành vi mới vào đối tượng bằng cách đặt đối tượng đó vào trong một đối tượng đặc biệt có chứa hành vi đấy\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nTưởng tượng bạn đang làm việc với một thư viện thông báo, nơi hỗ trợ các ứng dụng thông báo cho người dùng của họ khi có sự kiện quan trọng.\n\nPhiên bản ban đầu của thư viện dựa trên lớp `Notifier` chỉ gồm một vài trường, hàm khởi tạo và phương thức `send` duy nhất. Phương thức này nhận các tham số tin nhắn từ client và gửi tin đến danh sách email đã được truyền đến `notifier` thông qua hàm khởi tạo. Ứng dụng bên thứ ba sẽ hành động như một client, tạo và cấu hình đối tượng `notifier` một lần, sau đó sử dụng nó cho tất cả các sự kiện quan trọng diễn ra.\n\n![problem1](./assets/problem1.png)\n\nVào một thời điểm nào đó, bạn nhận về góp ý từ người dùng là họ mong muốn nhiều hơn thông báo từ email. Phần lớn họ muốn nhận thêm thông báo SMS. Số khác muốn thông báo trên Facebook, và một vài doanh nghiệp sử dụng muốn nhận thông báo từ Slack.\n\n![problem2](./assets/problem2.png)\n\nĐiều này phải thay đổi như thế nào? Bạn phải mở rộng lớp `Notifier` và thêm các phương thức thông báo bổ sung vào lớp con mới. Bây giờ client sẽ tạo lớp thông báo mong muốn và sử dụng nó cho tất cả thông báo trong tương lai.\n\nNhưng lại có thêm một góp ý nữa là \"Tại sao bạn không gửi nhiều kiểu thông báo cùng lúc? Nếu nhà bạn đang cháy, bạn có muốn nhận được thông tin từ mọi phương tiện không?\"\n\nBạn sẽ phải giải quyết thêm vấn đề này bằng cách tạo lớp con đặc biệt là kết hợp tất cả phương thức thông báo trong một lớp. Tuy nhiên, rất nhanh chóng để nhận ra là cách tiếp cận này làm cho code phình to lên, không chỉ là ở thư viện mà cả ở code client.\n\n![problem3](./assets/problem3.png)\n\nBạn cần tìm cách khác để cấu trúc lớp thông báo sao cho số lượng của chúng không vô tình phá vỡ kỷ lục Guinnesss.\n\n## 😊 Giải pháp\n\nMở rộng lớp bằng kế thừa là điều đầu tiên người ta nghĩ đến khi cần thay đổi hành vi đối tượng. Tuy nhiên, kế thừa có nhiều vấn đề mà ta cần phải biết:\n- Kế thừa là tĩnh. Bạn không thể thay đối hành vi của đối tượng đã tồn tại khi chạy. Bạn chỉ có thể thay thế đối tượng đấy với đối tượng khác được tạo từ lớp con khác.\n- Lớp con có thể chỉ có một lớp cha. Trong hầu hết ngôn ngữ, một lớp không thể kế thừa từ nhiều lớp cha vào cùng thời điểm.\n\nMột trong những cách khắc phục các vấn đề trên là sử dụng Aggregation(tổng hợp) hoặc Composition(phức hợp) thay vì kế thừa. Cả hai thay thế đều hoạt động giống nhau là tạo đối tượng tham chiếu đến đối tượng khác và uỷ quyền một số công việc cho đối tượng đấy. \nỞ kế thừa, bản thân đối tượng có thể thực hiện các công việc đó, bằng cách kế thừa hành vi từ lớp cha của nó.\n\nVới cách tiếp cận mới bạn có thể dễ dàng thay thế liên kết giữa đối tượng với một đối tượng khác, để thay đổi hành vi của chúng khi đang chạy. Một đối tượng có thể sử dụng hành vi của các lớp khác nhau, có tham chiều đến nhiều đối tượng và uỷ thác cho nó tất cả loại công việc.\n\n*Aggregation/composition* là nguyên tắc quan trọng đằng sau khá nhiều design pattern, bao gồm cả Decorator. Tuy nhiên, ta sẽ thảo luận về điều này sau.\n\n![solution1](./assets/solution1.png)\n\n**Wrapper** là tên thay thế cho Decorator đễ diễn đạt rõ ràng ý tưởng chính của pattern. Một Wrapper là một đối tượng có thể liên kết với một vài đối tượng đích(target). Wrapper chứa cùng một tập hợp phương thức như là target và ủy quyền cho nó tất cả các yêu cầu mà nó nhận được. Tuy nhiên, Wrapper có thể thay đổi kết quả bằng một vài hành động trước hoặc sau khi truyền yêu cầu đến target.\n\nKhi nào một wrapper đơn giản trở thành một decorator? Như đã nhấn mạnh, wrapper triển khai cùng một interface như một đối tượng được bọc. Đấy là lý do tại sao từ góc nhìn client tất cả đối tượng là như nhau. Các trường tham chiếu của wrapper chấp nhận bất kỳ đối tượng nào theo sau interface đấy. Điều này giúp bạn có thể bọc một đối tượng trong nhiều wrapper và thêm các hành vi kết hợp của tất cả wrapper cho nó.\n\nTrong ví dụ thư viện thông báo, ta chỉ chuyển phương thức thông báo email vào lớp cơ sở `Notifier`, và chuyển tất cả phương thức thông báo khác vào decorator.\n\n![solution2](./assets/solution2.png)\n\nCode client chỉ cần bọc đối tượng notifier đơn giản vào tập hợp của decorato ứng với mong muốn client. Đối tượng kết quả sẽ có cấu trúc như một ngăn xếp.\n\n![solution3](./assets/solution3.png)\n\nDecorator cuối cùng của ngăn xếp sẽ là đối tượng mà client thực sự làm việc. Vì tất cả decorator triển khai cùng interface, nên phần code client còn lại không quan tâm nó đang làm việc với đối tượng `notifier` thuần hay là decorator.\n\nTa có thể áp dụng cách tiếp cận này cho các hành vi khác như định dạng tin nhắn hoặc tạo danh sách người nhận. Client có thể tuỳ chỉnh đối tượng với bất kỳ decorator nào, miễn là nó theo cùng interface với những cái khác.\n\n## 🚗 Thế Giới Thực\n\n![analogy](./assets/analogy.png)\n\nMặc quần áo là ví dụ rõ ràng nhất sử dụng decorator. Khi bạn lạnh, bạn bọc cơ thể bằng áo len, khi vẫn còn lạnh bạn mặc thêm áo có mũ trên đầu. Nếu mưa bạn có thể dùng áo mưa. Tất cả những trang phục này “mở rộng” hành vi của bạn nhưng không phải là một phần của bạn và bạn có thể dễ dàng cởi bỏ bất kỳ bộ quần áo nào bất cứ khi không cần đến.\n\n## 🏢 Cấu trúc\n\n![structure](./assets/structure.png)\n\n1. **Component** khai báo interface chung cho wrapper và đối tượng được bọc.\n2. **Concrete Component** là lớp của đối tượng đang được bọc. Nó xác định các hành vi cơ bản, có thể bị thay đổi bởi decorator.\n3. **Base Decorator** là lớp có có trường tham chiếu đến đối tượng được bọc. Trường này tham chiếu đến interface component, thế nên nó có thể bao gồm concrete components và decorator. Base decorator uỷ thác tất cả công việc cho đối tượng được bọc.\n4. **Concrete Decorator** xác định hành vi mở rộng có thể thêm vào component một cách linh động. Concrete Decorator ghi đè phương thức của base decorator và thực thi hành vi của nó trước hoặc sau khi gọi phương thức cha.\n5. **Client** có thể bọc component trong nhiều lớp của decorator, miễn là nó làm việc với tất cả đối tượng thông qua interface chung.\n\n## 👨‍💻 Mã giả\n\nTrong ví dụ này, Decorator cho phép bạn nén và mã hóa dữ liệu quan trọng độc lập với phần code sử dụng dữ liệu này.\n\n![pseudocode](./assets/pseudocode.png)\n\nỨng dụng bọc đối tượng nguồn dữ liệu bằng một cặp decorator. Cả hai thay đổi cách dữ liệu được ghi và đọc từ ổ đĩa:\n- Trước khi ghi dữ liệu vào ổ đĩa, decorator mã hoá và nén nó lại. Lớp gốc ghi dữ liệu - đã được mã hoá và bảo vệ - vào file mà không cần biết về bất kỳ thay đổi gì.\n- Sau khi dữ liệu được đọc từ ổ đĩa, nó đi đến cùng decorator, nơi giải nén và giải mã nó.\n\nDecorator và lớp nguồn dữ liệu triển khai cùng interface, điều này làm cho tất cả chúng có thể hoán đổi cho nhau trong code client.\n\n```c\n// Interface component xác định hành vi có thể\n// thay đổi bởi decorator.\ninterface DataSource is\n    method writeData(data)\n    method readData():data\n\n// Concrete component cung cấp triển khai mặc định cho\n// các hành vi. Nó có thể có một số lớp biến thể khác\n// nhau trong chương trình.\nclass FileDataSource implements DataSource is\n    constructor FileDataSource(filename) { ... }\n\n    method writeData(data) is\n        // Ghi dữ liệu vào file\n\n    method readData():data is\n        // Đọc dữ liệu từ file.\n\n\n// Lớp base decorator theo cùng một interface như là component\n// khác. Mục đích chính của lớp này là xác định interface bọc\n// cho tất cả concrete decorator. Triển khai mặc định của code\n// bọc gồm một trường lưu trữ component được bọc và phương\n// thức để khởi tạo nó.\nclass DataSourceDecorator implements DataSource is\n    protected field wrappee: DataSource\n\n    constructor DataSourceDecorator(source: DataSource) is\n        wrappee = source\n\n    // Base decorator uỷ thác tất cả công việc cho các \n    // component được bọc. Các hành vi mở rộng có thể\n    // thêm vào concrete decorator.\n    method writeData(data) is\n        wrappee.writeData(data)\n\n    // Concrete decorator có thể gọi đến cha để triển khai \n    // hoạt động thay vì gọi trực tiếp đối tượng được bọc. \n    // Cách tiếp cận này đơn giản hoá việc mở rộng lớp decorator.\n    method readData():data is\n        return wrappee.readData()\n\n\n// Concrete decorator phải gọi phương thức trên đối tượng\n// được bọc, nhưng phải thêm một vài thứ của nó vào kết\n// quả. Docerator thực thi hành vi được thêm vào trước \n// hoặc sau khi gọi đối tượng được bọc.\nclass EncryptionDecorator extends DataSourceDecorator is\n    method writeData(data) is\n        // 1. Mã hoá dữ liệu truyền vào.\n        // 2. Truyên dữ liệu đã mã hoá vào phương thức\n        // writeData của wrappee\n\n    method readData():data is\n        // 1. Lấy dữ liệu từ phương thức readData của wrappee\n        // 2. Giải mã nếu nó được mã hoá\n        // 3. Trả về kết quả.\n\n// Bạn có thể bọc đối tượng trong nhiều lớp decorators.\nclass CompressionDecorator extends DataSourceDecorator is\n    method writeData(data) is\n        // 1. Nén dữ liệu truyền vào.\n        // 2. Truyền dữ liệu đã nén vào phương thức writeData\n        // của wrappee\n\n    method readData():data is\n        // 1. Lấy dữ liệu từ phương thức readData của wrappee\n        // 2. Giải nén nếu dữ liệu được nén\n        // 3. Trả về kết quả\n\n// Lựa chọn 1. Ví dụ đơn giản của decorator.\nclass Application is\n    method dumbUsageExample() is\n        source = new FileDataSource(\"somefile.dat\")\n        source.writeData(salaryRecords)\n        // File đích đã ghi dữ liệu thuần.\n\n        source = new CompressionDecorator(source)\n        source.writeData(salaryRecords)\n        // File đích đã ghi dữ liệu được nén.\n\n        source = new EncryptionDecorator(source)\n        // Biến source bây giờ bao gồm:\n        // Encryption > Compression > FileDataSource\n        source.writeData(salaryRecords)\n        // File đã ghi dữ liệu được nén và mã hoá.\n\n\n// Lựa chọn 2. Code client sử dụng nguồn dữ liệu bên ngoài.\n// Đối tượng SalaryManager không biết và cũng không quan tâm\n// nơi lưu trữ dữ liệu cụ thể. Nó làm việc với nguồn dữ liệu\n// cấu hình trước từ ứng dụng.\nclass SalaryManager is\n    field source: DataSource\n\n    constructor SalaryManager(source: DataSource) { ... }\n\n    method load() is\n        return source.readData()\n\n    method save() is\n        source.writeData(salaryRecords)\n    // ...Các phương thức hữu ích khác...\n\n\n// Ứng dụng có thể lắp ghép các decorator khác nhau của\n// ngăn xếp khi đang chạy, phù thuộc vào cấu hình hay\n// môi trường.\nclass ApplicationConfigurator is\n    method configurationExample() is\n        source = new FileDataSource(\"salary.dat\")\n        if (enabledEncryption)\n            source = new EncryptionDecorator(source)\n        if (enabledCompression)\n            source = new CompressionDecorator(source)\n\n        logger = new SalaryManager(source)\n        salary = logger.load()\n    // ...\n```\n\n## 💡 Ứng dụng\n\n**🐞 Sử dụng Decorator khi bạn cần thêm các hành vi bổ sung cho đối tượng khi đang chạy mà không làm ảnh hưởng đến code sử dụng đối tượng đó**\n\n⚡ Decorator cho phép bạn cấu trúc logic nghiệp vụ thành các lớp(layer), tạo decorator cho từng lớp và tạo đối tượng với các kết hợp khác nhau theo logic đấy khi đang chạy. Code client có thể xử lý mọi đối tượng giống nhau vì chúng theo cùng interface.\n\n**🐞 Sử dụng Decorator khi bạn cảm thấy khó khăn hoặc không thể mở rộng hành vi đối tượng bằng kế thừa**\n\n⚡ Một vài ngôn ngữ lập trình có từ khoá `final` để ngăn chặn mở rộng thêm lớp. Đối với lớp final, chỉ có một cách để mở rộng hành vi là bọc lớp đấy lại bằng Decorator.\n\n## 📋 Triển khai\n\n1. Đảm bảo rằng phần code nghiệp vụ có thể biểu diễn bằng một component chính với các lớp tuỳ chọn trên nó.\n2. Tìm ra phương thức chung cho component chính và các lớp tuỳ chọn. Tạo interface component và khai báo các phương thức cho nó.\n3. Tạo lớp concrete component và xác định hành vi cơ sở của nó.\n4. Tạo lớp decorator cơ sở. Nó nên có trường lưu trữ tham chiếu đến các đối tượng được bọc. Trường này nên khai báo cùng kiểu interface component để cho phép liên kết đến concrete component cũng như các decorator. Decorator cơ sở sẽ uỷ thác tất cả công việc cho các đối tượng được bọc.\n5. Đảm bảo tất cả lớp triển khai theo interface component.\n6. Tạo concrete decorator bằng cách mở rộng nó từ decorator cơ sở. Concrete decorator phải thực thi hành vi của nó trước hoặc sau gọi đến phương thức cha (nơi lưu uỷ thác công việc cho đối tượng được bọc).\n7. Code client phải chịu trách nhiệm tạo decorator và cấu trúc chúng khi cần sử dụng.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ Bạn có thể mở rộng hành vi của đối tượng mà không cần lớp con.\n\n✔️ Bạn có thể thêm hoặc xoá hành vi khỏi đối tượng khi đang chạy.\n\n✔️ Bạn có thể kết hợp nhiều hành vi bằng cách bọc đối tượng trong nhiều decorator.\n\n✔️ *Single Responsibility Principle*. Bạn có thể chia một khối lớp thành nhiều hành vi cho các lớp con.\n\n### Nhược điểm\n\n❌ Gặp khó khi xoá một wrapper cụ thể khỏi ngăn xếp.\n\n❌ Gặp khó khi triển khai decorator nếu hành vi của nó không theo thứ tự trong ngăn xếp.\n\n❌ Code cấu hình ban đầu của lớp sẽ rất tệ.\n\n## 🔁 Quan hệ với các pattern khác\n\n**Adapter** thay đổi interface của một đối tượng hiện có, trong khi **Decorator** nâng cao một đối tượng mà không thay đổi interface của nó. Ngoài ra, **Decorator** hỗ trợ thành phần đệ quy, điều này không thể thực hiện được khi bạn sử dụng **Adapter**.\n\n**Adapter** cung cấp một interface khác cho đối tượng được bọc, **Proxy** cung cấp cho nó một interface tương tự và **Decorator** cung cấp cho nó một interface nâng cao.\n\n**Chain of Responsibility** và **Decorator** có cấu trúc lớp rất giống nhau. Cả hai pattern đều dựa vào thành phần đệ quy để truyền việc thực thi qua một loạt các đối tượng. Tuy nhiên, có một số khác biệt quan trọng.\n\nCác trình xử lý **CoR** có thể thực hiện các hoạt động tùy ý độc lập với nhau. Nó cũng có thể ngừng chuyển yêu cầu thêm vào bất kỳ lúc nào. Mặt khác, các **Decorator** khác nhau có thể mở rộng hành vi của đối tượng trong khi vẫn giữ cho nó nhất quán với interface cơ sở. Ngoài ra, **Decorator** không được phép phá vỡ quy trình của yêu cầu.\n\n**Composite** và **Decorator** có các sơ đồ cấu trúc tương tự vì cả hai đều dựa vào thành phần đệ quy để tổ chức một số lượng các đối tượng kết thúc mở.\n\n- **Decorator** giống như **Composite** nhưng chỉ có một thành phần con. Sự khác biệt đáng kể khác là **Decorator** thêm các trách nhiệm bổ sung cho đối tượng được bao bọc, trong khi **Composite** chỉ \"tính tổng\" các kết quả con của nó.\n\n- Tuy nhiên, các pattern cũng có thể hợp tác: bạn có thể sử dụng **Decorator** để mở rộng hành vi của một đối tượng cụ thể trong cây **Composite**.\n\nCác thiết kế sử dụng nhiều **Composite** và **Decorator** thường có thể được hưởng lợi từ việc sử dụng **Prototype**. Áp dụng pattern cho phép bạn sao chép các cấu trúc phức tạp thay vì xây dựng lại chúng từ đầu.\n\n**Decorator** cho phép bạn thay đổi vẻ ngoài của một đối tượng, trong khi **Strategy** cho phép bạn thay đổi ruột.\n\n**Decorator** và **Proxy** có cấu trúc tương tự, nhưng nội dung rất khác nhau. Cả hai pattern đều được xây dựng trên cùng nguyên tắc, trong đó một đối tượng được cho là ủy quyền một số công việc cho đối tượng khác. Sự khác biệt là **Proxy** thường tự quản lý vòng đời của đối tượng dịch vụ của nó, trong khi thành phần của **Decorator** luôn được kiểm soát bởi client.\n\n# Nguồn \n\n[**refactoring**](https://refactoring.guru/design-patterns/decorator)"
  },
  {
    "path": "structural-pattern/facade/README.md",
    "content": "# Facade\n\n## 📜 Mục đích\n\n**Facade** là design pattern thuộc nhóm structural cung cấp interface đơn giản cho thư viện, framework hoặc bất kỳ tập hợp lớp phức tạp nào khác.\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nHãy tưởng tượng rằng bạn phải sử dụng code của mình để làm việc với một loạt các đối tượng thuộc về một thư viện hoặc framework phức tạp. Thông thường, bạn cần khởi tạo tất cả các đối tượng đó, theo dõi các phụ thuộc, thực thi các phương thức theo đúng thứ tự, ...\n\nDo đó, logic nghiệp vụ trong các lớp của bạn sẽ trở nên lệ thuộc chặt chẽ với các chi tiết triển khai của các lớp bên thứ ba, khiến cho việc hiểu rõ và bảo trì trở nên khó khăn.\n\n## 😊 Giải pháp\n\nFacade là một lớp cung cấp interface đơn giản cho cho một hệ thống con phức tạp chứa nhiều bộ phận chuyển động. Một facade có thể cung cấp chức năng hạn chế so với làm việc trực tiếp qua hệ thống con. Tuy nhiên, nó sẽ bao gồm những tính năng mà client thực sự quan tâm.\n\nCó một facade rất tiện lợi khi bạn cần tích hợp ứng dụng của mình với một thư viện phức tạp có hàng tá tính năng, nhưng bạn chỉ cần một vài chức năng trong đó\n\nVí dụ: một ứng dụng tải video ngắn hài hước về mèo lên mạng xã hội có thể sử dụng thư viện chuyển đổi video chuyên nghiệp. Tuy nhiên, tất cả những gì bạn thực sự cần là một lớp với một phương thức duy nhất `encode(filename, format)`. Sau khi tạo một lớp như vậy và kết nối nó với thư viện chuyển đổi video, bạn sẽ có facade đầu tiên của mình..\n\n## 🚗 Thế Giới Thực\n\n![analogy](./assets/analogy.png)\n\nKhi bạn gọi đến một cửa hàng để đặt hàng qua điện thoại, nhân viên tổng đài sẽ là facade của bạn đối với tất cả các dịch vụ và bộ phận của cửa hàng. Nhà điều hành cung cấp cho bạn một  interface giọng nói đơn giản với hệ thống đặt hàng, cổng thanh toán và các dịch vụ giao hàng khác nhau.\n\n## 🏢 Cấu trúc\n\n![structure](./assets/structure.png)\n\n1. **Facade** cung cấp khả năng truy cập thuận tiện vào một phần cụ thể của chức năng trong hệ thống con. Nó biết nơi định hướng yêu cầu của client và cách vận hành tất cả các bộ phận hoạt động.\n2. **Additional Facade**, lớp bổ sung có thể được tạo để ngăn chặn việc làm hỏng một facede đơn lẻ với các tính năng không liên quan khiến nó trở thành một cấu trúc phức tạp. Additional Facade có thể được sử dụng bởi client và facade khác.\n3. **Complex Subsystem** bao gồm hàng chục đối tượng khác nhau. Để tất cả bọn chúng làm điều gì đó có ý nghĩa, bạn phải đi sâu vào chi tiết triển khai của hệ thống con, chẳng hạn như khởi tạo các đối tượng theo đúng thứ tự và cung cấp cho chúng dữ liệu ở định dạng thích hợp.\nCác lớp hệ thống con không biết về sự tồn tại của facade. Chúng hoạt động trong hệ thống và làm việc trực tiếp với nhau.\n4. **Client** sử dụng facade thay vì gọi trực tiếp đến hệ thống con.\n\n## 👨‍💻 Mã giả\n\nTrong ví dụ này, Facade đơn giản hóa việc tương tác với một framework chuyển đổi video phức tạp.\n\n![pseudocode](./assets/pseudocode.png)\n\nThay vì sử dụng code của bạn làm việc trực tiếp với hàng chục lớp framework, bạn tạo một lớp facade đóng gói chức năng đó và ẩn nó khỏi phần code còn lại. Cấu trúc này cũng giúp bạn giảm thiểu việc nâng cấp lên các phiên bản trong tương lai của framework hoặc thay thế nó bằng một framework khác. Điều duy nhất bạn cần thay đổi trong ứng dụng của mình sẽ là triển khai các phương pháp của facade.\n\n```c\n// Đây là một số lớp phức tạp của framework chuyển đổi video\n// bên thứ 3. Ta không kiểm soát code này nên không đơn \n// giản nó được.\n\nclass VideoFile\n// ...\n\nclass OggCompressionCodec\n// ...\n\nclass MPEG4CompressionCodec\n// ...\n\nclass CodecFactory\n// ...\n\nclass BitrateReader\n// ...\n\nclass AudioMixer\n// ...\n\n\n// Ta tạo lớp facade để ẩn framework phức tạp sau interface\n// đơn giản. Nó là đánh đổi giữa đầy đủ chức năng và tính \n// đơn giản.\nclass VideoConverter is\n    method convert(filename, format):File is\n        file = new VideoFile(filename)\n        sourceCodec = new CodecFactory.extract(file)\n        if (format == \"mp4\")\n            destinationCodec = new MPEG4CompressionCodec()\n        else\n            destinationCodec = new OggCompressionCodec()\n        buffer = BitrateReader.read(filename, sourceCodec)\n        result = BitrateReader.convert(buffer, destinationCodec)\n        result = (new AudioMixer()).fix(result)\n        return new File(result)\n\n// Lớp ứng dụng không phụ thuộc vào hàng tỉ lớp được cung cấp\n// bởi framework phức tạp. Nếu bạn muốn đổi framework, bạn chỉ\n// cần viết lại lớp facade.\nclass Application is\n    method main() is\n        convertor = new VideoConverter()\n        mp4 = convertor.convert(\"funny-cats-video.ogg\", \"mp4\")\n        mp4.save()\n```\n\n## 💡 Ứng dụng\n\n**🐞 Sử dụng Facade khi bạn cần có một interface hạn chế nhưng đơn giản cho một hệ thống con phức tạp**\n\n⚡ Thông thường, các hệ thống con trở nên phức tạp hơn theo thời gian. Ngay cả việc áp dụng các design pattern thường dẫn đến việc tạo ra nhiều lớp hơn. Một hệ thống con có thể trở nên linh hoạt hơn và dễ dàng sử dụng lại trong các ngữ cảnh khác nhau, nhưng số lượng cấu hình và code có sẵn mà nó yêu cầu từ client ngày càng lớn hơn. Facade cố gắng khắc phục sự cố này bằng cách cung cấp một lối tắt đến các tính năng được sử dụng nhiều nhất của hệ thống con phù hợp với hầu hết các yêu cầu của client.\n\n**🐞 Sử dụng Facade khi bạn muốn cấu trúc một hệ thống con thành các lớp**\n\n⚡ Tạo các facade để xác định các điểm vào cho mỗi cấp của một hệ thống con. Bạn có thể giảm sự ghép nối giữa nhiều hệ thống con bằng cách yêu cầu chúng chỉ giao tiếp thông qua các facade.\n\nVí dụ: hãy quay lại framework chuyển đổi video. Nó có thể được chia thành hai lớp: liên quan đến video và âm thanh. Đối với mỗi lớp, bạn có thể tạo một facade và sau đó làm cho các lớp của mỗi lớp giao tiếp với nhau thông qua các facade. Cách tiếp cận này trông rất giống với **Mediator**.\n\n## 📋 Triển khai\n\n1. Kiểm tra xem liệu có thể cung cấp interface đơn giản hơn những gì hệ thống con hiện tại đã cung cấp hay không. Bạn đang đi đúng hướng nếu interface này làm cho code client độc lập với nhiều lớp của hệ thống con.\n2. Khai báo và triển khai interface này trong một lớp facade mới. Facade phải chuyển hướng các cuộc gọi từ code client đến các đối tượng thích hợp của hệ thống con. Facade phải chịu trách nhiệm khởi tạo hệ thống con và quản lý vòng đời tiếp theo của nó trừ khi code client đã thực hiện điều này.\n3. Để có được toàn bộ lợi ích từ thiết kế, hãy làm cho tất cả code client chỉ giao tiếp với hệ thống con thông qua facade. Bây giờ code client được bảo vệ khỏi bất kỳ thay đổi nào trong code hệ thống con. Ví dụ: khi một hệ thống con được nâng cấp lên phiên bản mới, bạn sẽ chỉ cần sửa đổi code trong facade.\n4. Nếu facade trở nên quá lớn, hãy xem xét trích xuất một phần hành vi của nó sang một lớp facade mới.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ Bạn có thể tách code của mình khỏi sự phức tạp của một hệ thống con.\n\n### Nhược điểm\n\n❌ Một facade có thể trở thành một đối tượng thần thánh cùng với tất cả các lớp của một ứng dụng. \n\n## 🔁 Quan hệ với các pattern khác\n\n**Facade** định nghĩa một interface mới cho các đối tượng hiện có, trong khi **Adapter** cố gắng làm cho interface hiện có có thể sử dụng được. **Adapter** thường chỉ bọc một đối tượng, trong khi **Facade** hoạt động với toàn bộ hệ thống con của các đối tượng.\n\n**Abstract Factory** có thể dùng như một giải pháp thay thế cho **Facade** khi bạn chỉ muốn ẩn cách các đối tượng hệ thống con được tạo ra khỏi code client.\n\n**Flyweight** cho thấy cách tạo nhiều đối tượng nhỏ, trong khi **Facade** cho thấy cách tạo một đối tượng duy nhất đại diện cho toàn bộ hệ thống con.\n\n**Facade** và **Mediator** có những công việc tương tự nhau: cố gắng tổ chức sự hợp tác giữa nhiều lớp được kết hợp chặt chẽ với nhau.\n\n- **Facade** xác định một interface đơn giản cho một hệ thống con của các đối tượng, nhưng nó không giới thiệu bất kỳ chức năng mới nào. Bản thân hệ thống con không biết về facade. Các đối tượng trong hệ thống con có thể giao tiếp trực tiếp.\n- **Mediator** tập trung giao tiếp giữa các thành phần của hệ thống. Các thành phần chỉ biết về đối tượng mediator và không giao tiếp trực tiếp.\n\nMột lớp **Facade** thường có thể được chuyển đổi thành **Singleton** vì một đối tượng facade duy nhất là đủ trong hầu hết các trường hợp.\n\n**Facade** tương tự như **Proxy** ở chỗ cả hai đều đệm một thực thể phức tạp và tự khởi tạo nó. Không giống như **Facade**, **Proxy** có interface giống với đối tượng dịch vụ của nó, điều này làm cho chúng có thể hoán đổi cho nhau.\n\n# Nguồn\n\n[**refactoring**](https://refactoring.guru/design-patterns/facade)\n"
  },
  {
    "path": "structural-pattern/flyweight/README.md",
    "content": "# Flyweight\n\n## 📜 Mục đích\n\n**Flyweight** là design pattern thuộc nhóm structural giúp bạn chỉnh các đối tượng phù hợp với dung lượng RAM bằng cách chia sẻ trạng thái chung giữa các đối tượng thay vì giữ tất cả dữ liệu ở một đối tượng.\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nĐể tìm điều gì vui vẻ sau thời gian dài làm việc, bạn quyết định tạo một video game đơn giản: người chơi di chuyển vòng quanh bản đồ và bắn hạ các đối thủ. Bạn chọn triển khai hệ thống hạt (hệ thống phổ biến nhất dùng làm game effect trong Unity 3d)  và tạo các tính năng đặc biệt cho game. Sẽ có rất nhiều mảnh đạn, tên lửa và mảnh bom từ các vụ nổ văng khắp bản đồ và mang lại trải nghiệm ly kỳ cho người chơi.\n\nSau hoàn thành, bạn commit lần cuối, tạo game và gửi nó cho người bạn để kiểm tra thử. Mặc dù game chạy hoàn hảo trên máy bạn, nhưng người bạn của bạn lại không thể chơi trong thời gian dài. Vì nó bị crash sau vài phút trên máy anh ta. Sau nhiều giờ tìm hiểu debug log, bạn nhận ra game bị crash vì nó không đủ RAM. Bởi vì máy tính của anh ta không mạnh như máy bạn, nên các sự cố mới xảy ra.\n\nThực ra vấn đề này có liên quan đến hệ thống hạt. Với mỗi hạt, ví dụ như đạn, tên lửa hay mảnh bom sẽ được biểu diễn bởi một đối tượng riêng bao gồm nhiều dữ liệu. Cùng thời điểm đó, nếu người chơi tàn sát lẫn nhau trên màn hình, các hạt mới tạo ra không vừa với dung lượng RAM còn lại, nên chương trình bị crash. \n\n![problem](./assets/problem.png)\n\n## 😊 Giải pháp\n\nKhi kiểm tra kỹ hơn các lớp `Particle`, bạn sẽ nhận ra các trường `color` và `sprite`(ảnh biểu diễn hạt) tiêu thụ nhiều bộ nhớ hơn các trường khác. Điều tệ ở đây là hai trường này lưu trữ phần lớn dữ liệu giống hệt nhau ở tất cả hạt. Ví dụ, tất cả đạn đều có cùng màu sắc và sprite.\n\n![solution1](./assets/solution1.png)\n\nMặt khác các trạng thái hạt như `coords`(toạ độ), `vector`(hướng chuyển động) và `speed`(tốc độ) là không trùng cho mỗi hạt. Đồng thời, giá trị các trường này sẽ thay đổi theo thời gian. Dữ liệu biểu diễn nó luôn thay đổi khi hạt tồn tại, trong khi màu sắc và sprite không đổi cho mỗi hạt.\n\nDữ liệu không đổi này của một đối tượng thường được gọi là *intrinsic state(trạng thái nội tại)*. Nó ở bên trong đối tượng; các đối tượng khác chỉ có thể đọc nó, không thể thay đổi nó. Phần còn lại của trạng thái của đối tượng, thường bị thay đổi “từ bên ngoài” bởi các đối tượng khác, được gọi là *extrinsic state(trạng thái bên ngoài)*.\n\nÝ tưởng của Flyweight là thay vì lưu trữ các trạng thái bên ngoài trong đối tượng. Bạn truyền trạng thái đó vào một phương thức cụ thể. Chỉ giữ lại trạng thái nội tại bên trong đối tượng, sử dụng nó cho các bối cảnh khác nhau. Do đó, bạn sẽ cần ít các đối tượng này hơn vì chúng chỉ khác nhau ở trạng thái nội tại, thứ có ít biến thể hơn nhiều so với trạng thái bên ngoài.\n\n![solution2](./assets/solution2.png)\n\nQuay lại với trò chơi ở trên. Giả sử rằng ta đã trích xuất trạng thái bên ngoài khỏi lớp `Particle`,  giờ chỉ còn ba đối tượng khác nhau là đủ để đại diện cho tất cả các hạt trong trò chơi: một viên đạn, một tên lửa và một mảnh bom. Như bạn có thể đã đoán, một đối tượng chỉ lưu trữ trạng thái bên trong được gọi là *flyweight*.\n\n### Lưu trữ trạng thái bên ngoài\n\nVậy trạng thái bên ngoài được chuyển đi đâu? Một vài lớp sẽ lưu trữ nó? Đúng vậy, đa số trường hợp nó được chuyển đến đối tượng container, thứ tổng hợp các đối tượng trước khi áp dụng pattern.\n\nỞ trường hợp này, đối tượng chính `Game` là nơi lưu trữ tất cả các hạt ở trường `particles`. Để chuyển trạng thái bên ngoài vào lớp này, bạn cần tạo nhiều trường kiểu mảng cho lưu trữ toạ độ, vector và tốc độ cho từng hạt. Đồng thời, bạn sẽ cần một mảng khác cho lưu trữ tham chiếu đến flyweight riêng để biểu diễn hạt. Các mảng này phải đồng bộ với nhau nên bạn phải truy cập tất cả dữ liệu của hạt với cùng một chỉ số.\n\n![solution3](./assets/solution3.png)\n\nGiải pháp gọn gàng hơn là tạo lớp ngữ cảnh riêng để lưu trữ trạng thái bên ngoài cùng với tham chiếu đến đối tượng flyweight. Cách tiếp cận này chỉ yêu cầu một mảng duy nhất trong lớp container.\n\nĐợi đã! Chúng ta không cần tất cả đối tượng ngữ cảnh như ban đầu sao? Về mặt kỹ thuật, thì đúng là như vậy. Nhưng hãy nhìn lại, các đối tượng bây giờ đã nhỏ hơn trước rất nhiều. Các trường tiêu thụ nhiều bộ nhớ nhất đã được chuyển vào các đối tượng flyweight. Bây giờ một ngàn đối tượng ngữ cảnh có thể sử dụng lại một đối tượng flyweight thay vì phải tự lưu trữ hàng ngàn bản sao dữ liệu.\n\n### Flyweight và tính bất biến\n\nVì cùng một đối tượng flyweight có thể dùng trong các bối cảnh khác nhau, bạn phải đảm bảo rằng nó không thể bị sửa đối. Một flyweight nên khởi tạo trạng thái một lần duy nhất, thông qua tham số từ hàm khởi tạo.Nó không được để lộ bấy kỳ setter hay trường công khai nào với đối tượng khác.\n\n### Flyweight factory\n\nĐể truy cập các flyweight khác nhau tiện lợi hơn, bạn có thể tạo phương thức factory để quản lý pool của đối tượng flyweight đã tồn tại. Phương thức chấp nhận trạng thái nội tại của flyweight mong muốn từ client, tìm kiếm flyweight đã tồn tại ứng với trạng thái này, và trả về nếu tìm gặp. Nếu không nó sẽ tạo flyweight mới và thêm vào pool.\n\nỞ đây có khá nhiều lựa chọn để đặt phương thức này. Đa số là ở flyweight container. Một vài trường hợp, bạn có thể tạo lớp factory mới. Hoặc bạn có thể tạo phương thức factory tĩnh và đặt vào trong nó lớp flyweight.\n\n## 🏢 Cấu trúc\n\n![structure](./assets/structure.png)\n\nFlyweight chỉ là một sự tối ưu hoá. Trước khi áp dụng nó, hãy đảm bảo chương trình của bạn có vấn đề tiêu thụ RAM liên quan đến số lượng khổng lồ các đối tượng giống nhau trong bộ nhớ cùng lúc. Đồng thời vấn đề này không thể giải quyết bằng bất kỳ cách nào khác.\n\n1. **Flyweight** lớp bao gồm phần trạng thái gốc của đối tượng có thể được chia sẻ giữa nhiều đối tượng. Cùng đối tượng flyweight có thể được sử dụng trong nhiều ngữ cảnh khác nhau. Trạng thái lưu trữ trong flyweight được gọi là *intrinsic*(nội tại). Trạng thái được chuyền đến phương thức của flyweight được gọi là *extrinsic*(bên ngoài).\n2. **Context** lớp bao gồm trạng thái bên ngoài, duy nhất trên tất cả đối tượng gốc. Khi context được ghép nối với một đối tượng flyweight, nó biểu diễn tất cả trạng thái của đối tượng gốc.\n3. Thông thường, hành vi của đối tượng gốc tồn tại trong lớp flyweight. Trong trường hợp này, bất cứ ai gọi phương thức của flyweight cũng phải truyền các bit phù hợp của trạng thái bên ngoài vào tham số của phương thức. Mặt khác, hành vi có thể được chuyền đến lớp context, nới sử dụng liên kết flyweight đơn thuần như một đối tượng dữ liệu.\n4. **Client** tính toán hoặc lưu trữ trạng thái bên ngoài của flyweight. Từ góc nhìn client, một flyweight là một đối tượng mẫu thứ có thể được cấu hình khi đang chạy bằng cách truyền một vài dữ liệu ngữ cảnh vào tham số của phương thức của nó.\n\n## 👨‍💻 Mã giả\n\nTrong ví dụ này, Flyweight giúp giảm mức sử dụng bộ nhớ khi hiển thị hàng triệu đối tượng dạng cây trên canvas.\n\n![structure](./assets/structure.png)\n\nPattern mở rộng trạng thái nội tại bị lặp của lớp `Tree` và chuyển nói vào lớp flyweight `TreeType`.\n\nBây giờ thay vì lưu trữ cùng một dữ liệu trong nhiều đối tượng, nó chỉ lưu trong vài đối tượng flyweight và liên kết đến đối tượng `Tree` phù hợp,thứ hành động như một context. Code client tạo đối tượng cây mới sử dụng flyweight factory, thứ gói gọn sự phức tạp của việc tìm kiếm đối tượng phù hợp và sử dụng lại nó nếu cần.\n\n```c\n// Lớp flyweight bao gồm một phần trạng thái của cây. Các\n// trường lưu trữ giá trị đơn nhất cho từng cây riêng biêt.\n// Ví dụ, bạn sẽ không tìm thấy ở đây toạ độ cây. Nhưng ở đây\n// sẽ có cấu hình và màu sắc được dùng cung giữa nhiều cây. \n// Vì dữ liệu này thường rất LỚN, bạn không muốn lãng phí phần\n// lớn bộ nhớ để lưu trữ nó cho từng đối tượng cây. Vì thế mà,\n// bạn trích xuất kết cấu, màu sắc và các dữ liệu lặp lại khác\n// vào một đối tượng riêng biệt mà các cây có thể tham chiếu\n// đến.\nclass TreeType is\n    field name\n    field color\n    field texture\n    constructor TreeType(name, color, texture) { ... }\n    method draw(canvas, x, y) is\n        // 1. Tạo bitmap cho kiểu, màu sắc và kết cấu.\n        // 2. Vẽ bitmap trên canvas theo toạ độ X và Y.\n\n// Flyweight factory quyết định xem sử dụng lại flyweight\n// hiện có hay tạo đối tượng mới.\nclass TreeFactory is\n    static field treeTypes: collection of tree types\n    static method getTreeType(name, color, texture) is\n        type = treeTypes.find(name, color, texture)\n        if (type == null)\n            type = new TreeType(name, color, texture)\n            treeTypes.add(type)\n        return type\n\n\n// Đối tượng ngữ cảnh bao gồm phần trạng thái bên ngoài của cây.\n// Ứng dụng có thể tạo hàng tỉ cái vì nó rất nhỏ: chỉ bao gồm hai\n// số nguyên cho toạ độ và một trường tham chiếu.\nclass Tree is\n    field x,y\n    field type: TreeType\n    constructor Tree(x, y, type) { ... }\n    method draw(canvas) is\n        type.draw(canvas, this.x, this.y)\n\n\n// Lớp Tree và Forest là client của flyweight.\n// Bạn có thể gộp chúng nếu không có ý đinh phát\n// triển lớp Tree xa hơn.\nclass Forest is\n    field trees: collection of Trees\n\n    method plantTree(x, y, name, color, texture) is\n        type = TreeFactory.getTreeType(name, color, texture)\n        tree = new Tree(x, y, type)\n        trees.add(tree)\n\n    method draw(canvas) is\n        foreach (tree in trees) do\n            tree.draw(canvas)\n```\n\n## 💡 Ứng dụng\n\n**🐞 Sử dụng Flyweight khi chương trình bạn tạo ra một số lượng lớn đối tượng không phù hợp với lượng RAM khả dụng**\n\n⚡ Lợi ích của áp dụng pattern này nằm ở việc nó được dùng như thế nào và ở đâu. Nó sẽ hữu ích nhất khi: \n- ứng dụng cần tạo một số lượng rất lớn đối tượng giống nhau.\n- điều này làm cạn RAM khả dụng của thiết bị\n- đối tượng bao gồm các trạng thái trùng lặp có thể trích xuất và chia sẻ giữa nhiều đối tượng.\n\n## 📋 Triển khai\n\n1. Chia các trường của lớp sẽ trở thành flyweight, thành hai phần:\n    - trạng thái nội tại: các trường dữ liệu không thay đổi trùng lặp với nhiều đối tượng\n    - trạng thái bên ngoài: các trường dữ liệu theo ngữ cảnh duy nhất cho mỗi đối tượng.\n2. Chuyển các trường biểu diễn trạng thái nội tại vào một lớp. Đảm bảo rằng nó luôn bất biến. Ta chỉ nên tạo trạng thái ban đầu cho nó trong hàm khởi tạo.\n3. Đi đến phương thức sử dụng trạng thái bên ngoài. Với từng trường sử dụng phương thức thêm tham số mới và dùng nó thay cho trường.\n4. Tuỳ chon, tạo lớp factory để quản lý pool của flyweight. Nó kiểm tra flyweight đã tồn tại trước khi tạo mới. Sau khi factory hoạt động, client nên gửi yêu cầu flyweight thông qua nó. Client có thể mô tả flyweight mong muốn bằng cách truyền trạng thái nội tại của nó đến factory.\n5. Client nên lưu trữ hoặc tính toán giá trị của trạng thái bên ngoài (ngữ cảnh) có thể gọi phương thức của đối tượng flyweight. Vì tiện lợi, trạng thái bên ngoài cùng với trường tham chiếu đến flyweight có thể được chuyển đến lớp ngữ cảnh riêng biệt.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ Bạn có thể tiết kiệm rất nhiều RAM, nếu chương trình của bạn có rất nhiều đối tượng giống nhau.\n\n### Nhược điểm\n\n❌ Bạn có thể trao đổi RAM quá mức với các chu kỳ CPU khi một số dữ liệu ngữ cảnh cần được tính toán lại mỗi khi ai đó gọi phương thức flyweight.\n\n❌ Code trở nên phức tạp hơn nhiều. Các thành viên mới trong nhóm sẽ luôn thắc mắc tại sao trạng thái của một thực thể lại được tách ra theo cách như vậy\n\n## 🔁 Quan hệ với các pattern khác\n\nBạn có thể triển khai các nút leaf chia sẻ của cây **Composite** dưới dạng **Flyweights** để tiết kiệm dung lượng RAM.\n\n**Flyweight** cho thấy cách tạo nhiều đối tượng nhỏ, trong khi **Facade** cho thấy cách tạo một đối tượng duy nhất đại diện cho toàn bộ hệ thống con.\n\n**Flyweight** sẽ giống với **Singleton** nếu bạn bằng cách nào đó giảm được tất cả các trạng thái được chia sẻ của các đối tượng xuống chỉ còn một đối tượng flyweight. Nhưng có hai điểm khác biệt cơ bản giữa các pattern này:\n\n- Chỉ nên có một thực thể **Singleton**, trong khi lớp **Flyweight** có thể có nhiều thực thể với các trạng thái nội tại khác nhau.\n- Đối tượng **Singleton** có thể thay đổi được. Đối tượng **Flyweight** là bất biến.\n\n# Nguồn\n\n[**refactoring**](https://refactoring.guru/design-patterns/flyweight)\n"
  },
  {
    "path": "structural-pattern/proxy/README.md",
    "content": "# Proxy\n\n## 📜 Mục đích\n\n**Proxy** là một design pattern thuộc nhóm structural cho phép bạn cung cấp một vật thay thế hoặc vật giữ chỗ cho một đối tượng khác. Một proxy kiểm soát quyền truy cập đến đối tượng ban đầu, cho phép bạn thực hiện điều gì đó trước hoặc sau khi yêu cầu được chuyển đến đối tượng ban đầu.\n\n![intent](./assets/intent.png)\n\n## 😟 Vấn đề\n\nTại sao bạn muốn kiểm soát truy cập đến một đối tượng? Hãy xem một ví dụ: nếu bạn có một đối tượng khổng lồ tiêu thụ một lượng lớn tài nguyên hệ thống. Bạn sẽ chỉ cần nó trong một vài thời điểm chứ không phải mọi lúc.\n\n![problem](./assets/problem.png)\n\nThế nên bạn có thể triển khai lazy initialization: tạo đối tượng chỉ khi thực sự cần đến nó. Tất cả đối tượng của client sẽ cần thực thi một số code deferred initialization. Thật không may điều này có thể gây ra code trùng lặp.\n\nNếu như đặt code này trực tiếp vào lớp đối tượng thì chỉ có thể thực hiện ở thế giới lý tưởng, vì thực tế lớp này có thể là một phần của một thư viện bên thứ 3.\n\n## 😊 Giải pháp\n\nProxy đưa ra ý tưởng rằng bạn nên tạo một lớp proxy mới với interface giống như đối tượng dịch vụ ban đầu. Sau đó, bạn cập nhật ứng dụng của mình để ứng dụng chuyển đối tượng proxy đến tất cả các client của đối tượng ban đầu. Khi nhận được yêu cầu từ client, proxy sẽ tạo một đối tượng dịch vụ thực và ủy thác tất cả công việc cho nó.\n\n![solution](./assets/solution.png)\n\n*Proxy cải trang bản thân như một đối tượng cơ sở dữ liệu. Nó có thể thực hiện lazy initialization và lưu kết quả vào bộ đêm mà cả cả client và cơ sở dữ liệu thực không hề biết.*\n\nVậy điều này có lợi ích gì? Nếu bạn cần thực thi điều gì đó trước hoặc sau logic chính của lớp, proxy sẽ giúp bạn làm điều đó mà không cần thay đổi lớp. Vì proxy triển khai cùng interface với lớp gốc, nên nó có thể được truyền đến bất kỳ client nào đang mong đợi một đối tượng dịch vụ thực.\n\n## 🚗 Thế Giới Thực \n\n![analogy](./assets/analogy.png)\n\nCredit card là một proxy cho một tài khoản khoản ngân hàng, thứ là proxy cho một khoản tiền mặt. Cả hai triển khai cùng interface để bạn có thể sử dụng nó cho thanh toán. Điều này làm khách hàng cảm thấy thoải mái vì họ không cần phải mang theo tiền mặt mọi lúc. Đồng thời chủ shop cũng cảm thấy vui vẻ vì số tiền từ một giao dịch điện tử đến tài khoản ngân hàng của shop sẽ giảm nguy cơ bị mất đặt cọc hay bị cướp trên đường. \n\n## 🏢 Cấu trúc\n\n![structure](./assets/structure.png)\n\n1. **Service Interface** khai báo interface của **Service**. Proxy phải theo sau interface này để có thể cải trang bản thân như một đối tượng dịch vụ.\n2. **Service** lớp cung cấp logic nghiệp vụ hữu ích thực sự.\n3. **Proxy** lớp có trường tham chiếu đến một đối tượng dịch vụ. Sau khi proxy kết thúc tiến trình của nó (lazy initialization, logging, điều khiển truy cập, catching,...) nó truyền yêu cầu đến đối tượng dịch vụ thực.\nThông thường, proxy quản lý chu kỳ hoàn chỉnh của đối tượng dịch vụ.\n4. **Client** nên làm việc với cả service và proxy thông qua cùng interface. Cách này giúp bạn có thể truyền proxy vào bất kỳ đoạn code nào cần một đối tượng dịch vụ.\n\n## 👨‍💻 Mã giả\n\nVí dụ này, minh họa cách Proxy có thể giúp lưu vào bộ nhớ cache và lazy initialization với thư viện tích hợp YouTube của bên thứ ba.\n\n![structure](./assets/structure.png)\n\nThư viện cung cấp cho ta một lớp để tải video về. Tuy nhiên, nó rất kém hiệu quả. Nếu ứng dụng client yêu cầu cùng một video nhiều lần, thư viện sẽ tải nó nhiều lần thay vì lưu vào bộ nhớ đệm và sử dụng lại file tải về đầu tiên.\n\nLóp proxy triển khai cùng interface như lớp tải về gốc và uỷ thác cho nó tất cả công việc. Tuy nhiên, nó sẽ theo dõi các file đã tải về và lấy kết quả từ bộ đệm khi ứng dụng yêu cầu cùng một video nhiều lần.\n\n```c\n// Interface của dịch vụ từ xa.\ninterface ThirdPartyYouTubeLib is\n    method listVideos()\n    method getVideoInfo(id)\n    method downloadVideo(id)\n\n\n// Triển khai cụ thể của dịch vụ kết nối. Phương thức của lớp\n// này có thể yêu cầu thông tin từ Youtube. Tốc độ của yêu cầu \n// dựa trên kết nối internet của người dùng cũng như của Youtube.\n// Ứng dụng sẽ tải chậm nếu có nhiều yêu cầu cùng lức, kể cả khi\n// tất cả yêu cầu cùng một thông tin.\nclass ThirdPartyYouTubeClass implements ThirdPartyYouTubeLib is\n    method listVideos() is\n        // Gửi yêu cầu API đến YouTube.\n\n    method getVideoInfo(id) is\n        // Lấy metadata về một vài video.\n\n    method downloadVideo(id) is\n        // Tải file video từ YouTube.\n\n\n// Để tiết kiệm brandwidth, bạn có thể lưu kết quả yêu cầu vào \n// bộ đệm và giữ nó cho một vài thời điểm. Nhưng không thể\n// đặt code trực tiếp vào lớp service. Ví dụ, nó có thể được\n// cung cấp như là một phần của thư viện bên thứ ba đã xác \n// định là `final`. Đó là lý do tại sao ta đặt code caching vào \n// lớp proxy mới, thứ triển khai interface giống như là lớp\n// service. Nó uỷ thác cho đối tượng service chỉ khi yêu cầu \n// thực sự cần gửi đi.\nclass CachedYouTubeClass implements ThirdPartyYouTubeLib is\n    private field service: ThirdPartyYouTubeLib\n    private field listCache, videoCache\n    field needReset\n\n    constructor CachedYouTubeClass(service: ThirdPartyYouTubeLib) is\n        this.service = service\n\n    method listVideos() is\n        if (listCache == null || needReset)\n            listCache = service.listVideos()\n        return listCache\n\n    method getVideoInfo(id) is\n        if (videoCache == null || needReset)\n            videoCache = service.getVideoInfo(id)\n        return videoCache\n\n    method downloadVideo(id) is\n        if (!downloadExists(id) || needReset)\n            service.downloadVideo(id)\n\n\n// Lớp GUI, thứ đã từng làm việc trực tiếp với đối tượng service,\n// không cần thay đổi gì miễn là nó làm việc với đối tượng service\n// thông qua một interface. Ta có thể truyền đối tượng proxy thay\n// vì đối tượng service thực vì cả hai triển khai cùng interface.\nclass YouTubeManager is\n    protected field service: ThirdPartyYouTubeLib\n\n    constructor YouTubeManager(service: ThirdPartyYouTubeLib) is\n        this.service = service\n\n    method renderVideoPage(id) is\n        info = service.getVideoInfo(id)\n        // Hiển thị trang video.\n\n    method renderListPanel() is\n        list = service.listVideos()\n        // Hiển thi danh sách hình ảnh của video.\n\n    method reactOnUserInput() is\n        renderVideoPage()\n        renderListPanel()\n\n// Ứng dụng có thể cấu hình proxy đang chạy.\nclass Application is\n    method init() is\n        aYouTubeService = new ThirdPartyYouTubeClass()\n        aYouTubeProxy = new CachedYouTubeClass(aYouTubeService)\n        manager = new YouTubeManager(aYouTubeProxy)\n        manager.reactOnUserInput()\n```\n\n## 💡 Ứng dụng\n\nCó rất nhiều cách để sử dụng Proxy. Hãy cùng điểm qua những cách sử dụng phổ biến nhất.\n\n**🐞 Lazy intialization (virtual proxy). Khi bạn có một đối tượng dịch vụ nặng gây lãng phí tài nguyên hệ thống do luôn hoạt động, mặc dù thỉnh thoảng bạn mới cần nó.**\n\n⚡ Thay vì tạo đối tượng khi ứng dụng khởi chạy, bạn có thể trì hoãn việc khởi chạy đối tượng đến thời điểm thực sự cần thiết.\n\n**🐞 Kiểm soát truy cập (protection proxy). Khi bạn muốn chỉ những client cụ thể mới có thể sử dụng đối tượng dịch vụ.**\n\n⚡ Ví dụ: khi các đối tượng của bạn là các phần quan trọng của hệ điều hành và các ứng dụng client là các ứng dụng được khởi chạy khác nhau (bao gồm cả những ứng dụng độc hại).\n\nProxy có thể chuyển yêu cầu đến đối tượng dịch vụ nếu thông tin đăng nhập của client phù hợp với một số tiêu chí.\n\n**🐞 Thực thi cục bộ một dịch vụ từ xa (remote proxy). Khi đối tượng dịch vụ được đặt trên một máy chủ từ xa.**\n\n⚡ Trong trường hợp này, proxy chuyển yêu cầu của client qua mạng, xử lý tất cả các chi tiết khó chịu khi làm việc với mạng.\n\n**🐞 Logging request (logging proxy). Khi bạn muốn giữ lịch sử của các yêu cầu đối với đối tượng dịch vụ.**\n\n⚡ Proxy có thể ghi lại từng yêu cầu trước khi chuyển nó đến dịch vụ.\n\n**🐞 Lưu kết quả yêu cầu vào bộ đệm (caching proxy). Khi bạn cần lưu vào bộ đệm kết quả của các yêu cầu client và quản lý vòng đời của bộ đệm này, đặc biệt nếu kết quả khá lớn.**\n\n⚡ Proxy có thể triển khai bộ nhớ đệm cho các yêu cầu định kỳ luôn mang lại kết quả giống nhau. Proxy có thể sử dụng các tham số của yêu cầu làm khóa bộ nhớ cache.\n\n**🐞 Tham chiếu thông minh. Khi bạn cần loại bỏ một đối tượng nặng khi không có ứng dụng client nào sử dụng nó.**\n\n⚡ Proxy có thể theo dõi các client nhận được tham chiếu đến đối tượng dịch vụ hoặc kết quả của nó. Đôi khi, proxy có thể đi qua các client và kiểm tra xem chúng có còn hoạt động hay không. Nếu danh sách client trống, proxy có thể loại bỏ đối tượng dịch vụ và giải phóng tài nguyên hệ thống.\n\nProxy cũng có thể theo dõi xem client đã sửa đổi đối tượng dịch vụ hay chưa. Sau đó, các đối tượng không thay đổi có thể được sử dụng lại bởi các client khác.\n\n## 📋 Triển khai\n\n1. Nếu không có interface dịch vụ nào có sẵn, hãy tạo một interface để làm cho các đối tượng proxy và dịch vụ có thể hoán đổi cho nhau. Không phải lúc nào bạn cũng có thể trích xuất interface khỏi lớp dịch vụ vì bạn cần thay đổi tất cả các client của dịch vụ sử dụng interface đó. Kế hoạch B là làm cho proxy trở thành lớp con của lớp dịch vụ và theo cách này nó sẽ kế thừa interface của dịch vụ.\n2. Tạo lớp proxy. Nó phải có một trường để lưu trữ một tham chiếu đến dịch vụ. Thông thường, proxy tạo và quản lý toàn bộ vòng đời của các dịch vụ của họ. Trong những trường hợp hiếm hoi, một dịch vụ được client chuyển tới proxy thông qua một phương thức khởi tạo.\n3. Thực hiện các phương pháp ủy quyền theo mục đích của chúng. Trong hầu hết các trường hợp, sau khi thực hiện một số công việc, proxy sẽ ủy quyền công việc cho đối tượng dịch vụ.\n4. Xem xét việc thêm một phương pháp tạo quyết định xem client nhận được một proxy hay một dịch vụ thực sự. Đây có thể là một phương thức tĩnh đơn giản trong lớp proxy hoặc một phương thức gốc đầy đủ.\n5. Xem xét việc triển khai lazy initialization cho đối tượng dịch vụ.\n\n## ⚖️ Ưu nhược điểm\n\n### Ưu điểm\n\n✔️ Bạn có thể kiểm soát đối tượng dịch vụ mà client không biết về nó.\n\n✔️ Bạn có thể quản lý vòng đời của đối tượng dịch vụ khi client không quan tâm đến nó.\n\n✔️ Proxy hoạt động ngay cả khi đối tượng dịch vụ chưa sẵn sàng hoặc không có sẵn.\n\n✔️ *Open/Closed Principle*. Bạn có thể thêm proxy mới mà không cần thay đổi dịch vụ hoặc ứng dụng client.\n\n### Nhược điểm\n\n❌ Code có thể trở nên phức tạp hơn vì bạn cần giới thiệu nhiều lớp mới.\n\n❌ Phản hồi từ dịch vụ có thể bị trì hoãn.\n\n\n## 🔁 Quan hệ với các pattern khác\n\n**Adapter** cung cấp một interface khác cho đối tượng được bọc, **Proxy** cung cấp cho nó một interface tương tự và **Decorator** cung cấp cho nó một interface nâng cao.\n\n**Decorator** và **Proxy** có cấu trúc tương tự, nhưng nội dung rất khác nhau. Cả hai pattern đều được xây dựng trên cùng nguyên tắc, trong đó một đối tượng được cho là ủy quyền một số công việc cho đối tượng khác. Sự khác biệt là **Proxy** thường tự quản lý vòng đời của đối tượng dịch vụ của nó, trong khi thành phần của **Decorator** luôn được kiểm soát bởi client.\n\n**Facade** tương tự như **Proxy** ở chỗ cả hai đều đệm một thực thể phức tạp và tự khởi tạo nó. Không giống như **Facade**, **Proxy** có interface giống với đối tượng dịch vụ của nó, điều này làm cho chúng có thể hoán đổi cho nhau.\n\n# Nguồn\n\n[**refactoring**](https://refactoring.guru/design-patterns/proxy)\n"
  }
]