├── .DS_Store ├── .github ├── FUNDING.yml └── workflows │ └── deploy.yml ├── .idea ├── Design-Patterns.iml ├── misc.xml ├── modules.xml ├── vcs.xml └── workspace.xml ├── CONTRIBUTING.md ├── Design-Patterns.iml ├── LICENSE.md ├── README.md ├── SUMMARY.md ├── Writerside ├── .DS_Store ├── c.list ├── cfg │ ├── buildprofiles.xml │ └── google-analytics-noscript.html ├── hi.tree ├── images │ ├── completion_procedure.png │ ├── completion_procedure_dark.png │ ├── convert_table_to_xml.png │ ├── convert_table_to_xml_dark.png │ ├── new_topic_options.png │ └── new_topic_options_dark.png ├── redirection-rules.xml ├── topics │ ├── Abstract-Factory.md │ ├── Adapter.md │ ├── Behavioral-Patterns.md │ ├── Bridge.md │ ├── Builder.md │ ├── Chain-Of-Responsibility.md │ ├── Command.md │ ├── Composite.md │ ├── Creational-Patterns.md │ ├── Decorator.md │ ├── Facade.md │ ├── Factory-Method.md │ ├── Flyweight.md │ ├── Intro.md │ ├── Iterator.md │ ├── Mediator.md │ ├── Memento.md │ ├── Observer.md │ ├── Prototype.md │ ├── Proxy.md │ ├── Singleton.md │ ├── State.md │ ├── Strategy.md │ ├── Structural-Patterns.md │ ├── Template-Method.md │ └── Visitor.md ├── v.list └── writerside.cfg ├── docs ├── .DS_Store ├── Book │ ├── 1. Intro.md │ ├── 2. Creational Patterns.md │ ├── 2.1 Singleton.md │ ├── 2.2 Builder.md │ ├── 2.3 Factory Method.md │ ├── 2.4 Abstract Factory.md │ ├── 2.5 Prototype.md │ ├── 3. Structural Patterns.md │ ├── 3.1 Adapter.md │ ├── 3.2 Bridge.md │ ├── 3.3 Composite.md │ ├── 3.4 Decorator.md │ ├── 3.5 Facade.md │ ├── 3.6 Flyweight.md │ ├── 3.7 Proxy.md │ ├── 4. Behavioral Patterns.md │ ├── 4.1 Chain of Responsibility.md │ ├── 4.10 Visitor.md │ ├── 4.2 Command.md │ ├── 4.3 Iterator.md │ ├── 4.4 Mediator.md │ ├── 4.5 Memento.md │ ├── 4.6 Observer.md │ ├── 4.7 State.md │ ├── 4.8 Strategy.md │ ├── 4.9 Template Method.md │ ├── 5. Read World.md │ ├── 6. Conclusion.md │ └── Struct.md ├── diagrams │ ├── Adapter.drawio │ ├── Bridge.drawio │ ├── ChainOfResponsibility.drawio │ ├── Command.drawio │ ├── Composite.drawio │ ├── Decorator.drawio │ ├── Facade.drawio │ ├── Iterator.drawio │ ├── Proxy.drawio │ └── Singleton.drawio └── images │ ├── .DS_Store │ ├── Adapter │ ├── Adapter.jpg │ ├── Adapter2.jpg │ ├── Result.PNG │ ├── Solution.jpg │ ├── pin3.jpg │ └── problem.jpg │ ├── Bridge │ ├── Problem Diagram-Page-2.png │ ├── Solution Diagram-Page-3.png │ ├── Struct Diagram.png │ └── Untitled Diagram.png │ ├── Chain Of Responsibility │ ├── problem.png │ ├── problem2.png │ ├── solution.png │ ├── struct.png │ └── vidu.png │ ├── Command │ ├── problem.png │ ├── solution.png │ ├── solution2.png │ ├── struct.png │ └── vidu.png │ ├── Composite │ ├── problem.png │ ├── struct.png │ └── vidu.png │ ├── Decorator │ ├── Problem.png │ ├── Problem2.png │ ├── Solution.png │ ├── Vidu.png │ └── struct.png │ ├── Facade │ ├── Struct Diagram.png │ └── Vidu Diagram.png │ ├── Iterator │ ├── Vidu.png │ ├── solution.png │ └── struct.png │ ├── OpenBookImage.png │ ├── Proxy │ ├── Vidu.png │ ├── problem.png │ ├── solution.png │ └── struct.png │ ├── Singleton │ ├── Singleton.png │ ├── Singleton1.png │ └── Singleton2.png │ └── bmc_qr.png └── src ├── .DS_Store ├── Behavioral Patterns ├── .DS_Store ├── Chain Of Responsibility │ ├── Demo.class │ ├── RawDataTest.class │ ├── RoleTest.class │ ├── Server.class │ ├── Test.class │ └── UserExistsTest.class ├── Command │ ├── Account.kt │ ├── BankApp.kt │ ├── CloseAccount.kt │ ├── Command.kt │ ├── OpenAccount.kt │ └── main.kt └── Iterator │ ├── Item.class │ ├── ItemIterator.class │ ├── IterableCollection.class │ ├── MenuCollection.class │ └── demo.class └── structural patterns ├── .DS_Store ├── Adapter ├── AdapterElectric.class ├── Led.class ├── LedInterFace.class └── VietNamPower.class ├── Bridge ├── Account.class ├── Bank.class ├── CheckingAccount.class ├── MMBank.class ├── TPBank.class ├── TutorialAccount.class └── demo.class ├── Composite ├── FileComponent.kt ├── FileLeaf.kt ├── FolderComposite.kt └── main.kt ├── Decorator ├── Notifier.kt ├── NotifierBaseDecorator.kt ├── NotifierConcrete.kt ├── Notifier_FB.kt ├── Notifier_SMS.kt ├── Notifier_Slack.kt └── main.kt ├── Facede ├── Demo.class ├── LoginService.class ├── NotiService.class ├── PayService.class ├── ShipService.class └── ShopFacade.class └── Proxy ├── ProxyVideo.kt ├── RealVideo.kt ├── Video.kt └── main.kt /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/.DS_Store -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: nguyenphuc22 4 | custom: ['https://www.buymeacoffee.com/phucvr'] 5 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Build documentation 2 | 3 | on: 4 | # If specified, the workflow will be triggered automatically once you push to the `main` branch. 5 | # Replace `main` with your branch’s name 6 | push: 7 | branches: ["main"] 8 | # Specify to run a workflow manually from the Actions tab on GitHub 9 | workflow_dispatch: 10 | 11 | # Gives the workflow permissions to clone the repo and create a page deployment 12 | permissions: 13 | id-token: write 14 | pages: write 15 | 16 | env: 17 | # Name of module and id separated by a slash 18 | INSTANCE: Writerside/hi 19 | # Replace HI with the ID of the instance in capital letters 20 | ARTIFACT: webHelpHI2-all.zip 21 | # Writerside docker image version 22 | DOCKER_VERSION: 232.10165.1 23 | # Add the variable below to upload Algolia indexes 24 | # Replace HI with the ID of the instance in capital letters 25 | ALGOLIA_ARTIFACT: algolia-indexes-HI.zip 26 | 27 | jobs: 28 | build: 29 | runs-on: ubuntu-latest 30 | 31 | steps: 32 | - name: Checkout repository 33 | uses: actions/checkout@v3 34 | 35 | - name: Build Writerside docs using Docker 36 | uses: JetBrains/writerside-github-action@v4 37 | with: 38 | instance: ${{ env.INSTANCE }} 39 | artifact: ${{ env.ARTIFACT }} 40 | docker-version: ${{ env.DOCKER_VERSION }} 41 | 42 | - name: Upload documentation 43 | uses: actions/upload-artifact@v3 44 | with: 45 | name: docs 46 | path: | 47 | artifacts/${{ env.ARTIFACT }} 48 | artifacts/report.json 49 | retention-days: 7 50 | 51 | # Add the step below to upload Algolia indexes 52 | - name: Upload algolia-indexes 53 | uses: actions/upload-artifact@v3 54 | with: 55 | name: algolia-indexes 56 | path: artifacts/${{ env.ALGOLIA_ARTIFACT }} 57 | retention-days: 7 58 | 59 | # Add the job below and artifacts/report.json on Upload documentation step above if you want to fail the build when documentation contains errors 60 | test: 61 | # Requires build job results 62 | needs: build 63 | runs-on: ubuntu-latest 64 | 65 | steps: 66 | - name: Download artifacts 67 | uses: actions/download-artifact@v1 68 | with: 69 | name: docs 70 | path: artifacts 71 | 72 | - name: Test documentation 73 | uses: JetBrains/writerside-checker-action@v1 74 | with: 75 | instance: ${{ env.INSTANCE }} 76 | 77 | deploy: 78 | environment: 79 | name: github-pages 80 | url: ${{ steps.deployment.outputs.page_url }} 81 | # Requires the build job results 82 | needs: test 83 | runs-on: ubuntu-latest 84 | steps: 85 | - name: Download artifact 86 | uses: actions/download-artifact@v3 87 | with: 88 | name: docs 89 | 90 | - name: Unzip artifact 91 | uses: montudor/action-zip@v1 92 | with: 93 | args: unzip -qq ${{ env.ARTIFACT }} -d dir 94 | 95 | - name: Setup Pages 96 | uses: actions/configure-pages@v2 97 | 98 | - name: Upload artifact 99 | uses: actions/upload-pages-artifact@v1 100 | with: 101 | path: dir 102 | 103 | - name: Deploy to GitHub Pages 104 | id: deployment 105 | uses: actions/deploy-pages@v1 106 | -------------------------------------------------------------------------------- /.idea/Design-Patterns.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 18 | 19 | 20 | 21 | 22 | 80 | 81 | 82 | 84 | { 85 | "associatedIndex": 0 86 | } 87 | 88 | 89 | 92 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 1700963735312 125 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Hướng dẫn đóng góp 2 | 3 | Chào mừng bạn đến với dự án "Open Book - Design Pattern Tiếng Việt"! Chúng tôi rất cảm kích sự quan tâm của bạn đến việc đóng góp vào quyển sách này. Để đảm bảo quy trình đóng góp diễn ra một cách thuận lợi và hiệu quả, hãy làm theo hướng dẫn dưới đây: 4 | 5 | ## 1. Đề xuất thay đổi 6 | 7 | Trước khi bắt đầu đóng góp, hãy đảm bảo kiểm tra **Issues** của repository để xem xét các vấn đề hiện có và các tính năng đang được đề xuất. Nếu bạn muốn đóng góp một tính năng mới hoặc sửa lỗi, vui lòng tạo một **Issue** mới để thông báo cho nhóm phát triển biết. 8 | 9 | ## 2. Fork repository 10 | 11 | Hãy **Fork** repository này bằng cách nhấn vào nút "Fork" ở góc trên bên phải trang. Điều này sẽ tạo một bản sao của repository này trên tài khoản GitHub của bạn. 12 | 13 | ## 3. Tạo branch mới 14 | 15 | Tạo một branch mới để làm việc trên dự án. Đặt tên branch sao cho dễ hiểu và miêu tả nội dung công việc mà bạn đang làm. 16 | 17 | ```shell 18 | git checkout -b ten_branch 19 | ``` 20 | 21 | 22 | ## 4. Thực hiện các thay đổi 23 | 24 | Thực hiện các thay đổi và cập nhật tài liệu một cách cẩn thận. Hãy chắc chắn rằng mã nguồn của bạn tuân thủ các quy tắc lập trình và được chú thích đầy đủ. 25 | 26 | ## 5. Commit và push 27 | 28 | Commit các thay đổi của bạn với mô tả chi tiết. 29 | 30 | ```shell 31 | git commit -m "Mô tả commit" 32 | ``` 33 | 34 | Push branch của bạn lên repository của bạn. 35 | 36 | ```shell 37 | git push origin ten_branch 38 | ``` 39 | ## 6. Tạo Pull Request 40 | 41 | Tạo **Pull Request** từ branch của bạn vào branch "main" trong repository chính. Vui lòng cung cấp mô tả chi tiết về các thay đổi và tính năng bạn đã thêm vào. 42 | 43 | ## 7. Review và hợp nhất 44 | 45 | Nhóm phát triển sẽ xem xét và review các thay đổi của bạn. Sau khi review thành công và thống nhất, chúng tôi sẽ **merge** Pull Request của bạn vào dự án. 46 | 47 | ## 8. Chúc mừng, bạn đã đóng góp thành công! 48 | 49 | Cảm ơn bạn đã đóng góp và hỗ trợ chúng tôi trong việc xây dựng quyển sách "Open Book - Design Pattern". Đóng góp của bạn sẽ giúp nâng cao kiến thức và kỹ năng lập trình cho cộng đồng người dùng ở Việt Nam. 50 | 51 | Nếu bạn có bất kỳ câu hỏi hoặc cần trợ giúp, hãy đăng câu hỏi trong phần **Issues** của repository. Chúng tôi rất sẵn lòng hỗ trợ bạn! 52 | -------------------------------------------------------------------------------- /Design-Patterns.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright © `2023` `Nguyen Phuc` 5 | 6 | Permission is hereby granted, free of charge, to any person 7 | obtaining a copy of this software and associated documentation 8 | files (the “Software”), to deal in the Software without 9 | restriction, including without limitation the rights to use, 10 | copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the 12 | Software is furnished to do so, subject to the following 13 | conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | OTHER DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sách - Design Pattern Tiếng Việt 2 | 3 | Xin chào và cảm ơn bạn đã ghé thăm repository của tôi - nơi chia sẻ kiến thức về Design Pattern. Dự án "Sách - Design Pattern Tiếng Việt" không chỉ là một cuốn sách, mà còn là một hành trình học hỏi, trao đổi và phát triển kỹ năng lập trình một cách chuyên nghiệp. 4 | 5 | Repository này được tạo ra với mục đích chia sẻ miễn phí kiến thức về các mẫu thiết kế phần mềm (Design Patterns) - một lĩnh vực thiết yếu và thách thức trong ngành lập trình. Tôi mong muốn mang đến cho cộng đồng lập trình Việt Nam một nguồn tài liệu tham khảo đáng giá, giúp cải thiện kỹ năng phân tích và thiết kế phần mềm. 6 | 7 | Trong repository "Sách - Design Pattern Tiếng Việt", bạn sẽ tìm thấy: 8 | 9 | - Hiểu rõ hơn về các Design Pattern phổ biến như Singleton, Observer, Strategy, etc. 10 | - Biết cách vận dụng các Design Pattern để giải quyết các vấn đề trong lập trình. 11 | - Có thể viết code sạch hơn, dễ bảo trì và mở rộng hơn. 12 | - Rèn luyện được kỹ năng phân tích, tư duy trừu tượng và giải quyết vấn đề. 13 | 14 |
15 | 16 |
17 | 18 | ## Ngôn ngữ được hỗ trợ 19 | 20 | - Tiếng Việt 21 | - Java 22 | 23 | ## Nội dung sách 24 | 25 | - [Chương 1: Giới thiệu Design Pattern](Writerside/topics/Intro.md) 26 | - [Chương 2: Nhóm Creational Patterns](Writerside/topics/Creational-Patterns.md) 27 | - [Chương 3: Nhóm Structural Patterns](Writerside/topics/Structural-Patterns.md) 28 | - [Chương 4: Nhóm Behavioral Patterns](Writerside/topics/Behavioral-Patterns.md) 29 | - [Chương 5: Ứng dụng thực tế](docs/Book/5.%20Read%20World.md) 30 | - [Kết luận](docs/Book/6.%20Conclusion.md) 31 | 32 | ## Đóng góp 33 | 34 | **Tham Gia Xây Dựng Cùng Chúng Tôi** 35 | 36 | Cuốn sách "Design Pattern Tiếng Việt" không chỉ là một dự án cá nhân mà là kết quả của sự cộng tác và đam mê chung của cả cộng đồng. Mỗi trang, mỗi chương, từng dòng code mà bạn đọc đều là minh chứng cho tinh thần hợp tác và chia sẻ kiến thức. 37 | 38 | Dự án này, từ ngày đầu tiên, đã cam kết là nguồn tài nguyên miễn phí, chất lượng cao cho tất cả mọi người, từ sinh viên đến các chuyên gia lập trình. Để duy trì và phát triển dự án này, chúng tôi kêu gọi sự hỗ trợ từ cộng đồng - không chỉ dưới hình thức đóng góp [nội dung](/README.md), mà còn qua sự hỗ trợ tài chính. 39 | 40 | Nếu bạn cảm thấy cuốn sách này mang lại giá trị cho bản thân và cộng đồng, xin hãy xem xét việc đóng góp tài chính qua trang [Buy Me a Coffee](https://www.buymeacoffee.com/phucvr). Mỗi đóng góp, dù nhỏ, đều là nguồn động viên lớn lao giúp chúng tôi tiếp tục công việc này. 41 | 42 |
43 | 44 |
45 | 46 | **Đóng góp của bạn sẽ được sử dụng để:** 47 | 48 | - Duy trì và nâng cấp dự án. 49 | - Hỗ trợ tác giả và người đóng góp. 50 | 51 | Tôi biết rằng, không phải ai cũng có khả năng đóng góp tài chính, và sự hỗ trợ về mặt tinh thần cũng rất quan trọng. Do đó, Star và chia sẻ dự án này với bạn bè, đồng nghiệp, và trên các mạng xã hội cũng là một hình thức đóng góp vô cùng quý giá. 52 | 53 | Dù là sự hỗ trợ nào, chúng tôi đều trân trọng và biết ơn. Cảm ơn bạn đã là một phần của hành trình này! 54 | 55 | ## Câu hỏi và Thảo luận 56 | 57 | Bạn có thắc mắc, ý kiến, hoặc cần hỗ trợ về các nội dung trong sách, các mẫu thiết kế phần mềm, hoặc cách áp dụng chúng trong thực tiễn lập trình? Hãy mạnh dạn chia sẻ và đặt câu hỏi của bạn trong phần "Issues" trên trang GitHub của dự án. Cùng nhau, tôi và cộng đồng của chúng ta sẽ nỗ lực giải đáp và thảo luận, nhằm mang lại lời giải rõ ràng và hữu ích cho mỗi vấn đề. 58 | 59 | Thêm vào đó, những câu hỏi nhận được sự quan tâm rộng rãi và nhiều lượt tương tác sẽ được xem xét để tích hợp trong các bản cập nhật tương lai của sách. Mục tiêu của chúng tôi không chỉ dừng lại ở việc chia sẻ kiến thức; chúng tôi còn muốn khuyến khích sự tương tác, học hỏi lẫn nhau, và cùng nhau đóng góp vào sự phát triển của cộng đồng lập trình Việt Nam. 60 | 61 | ## Cảm ơn 62 | 63 | Cảm ơn bạn đã quan tâm và đồng hành cùng dự án! 64 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Mục lục 2 | 3 | - [Chương 1: Giới thiệu Design Pattern](docs/Book/1.%20Intro.md) 4 | - Khái niệm Design Pattern 5 | - Lịch sử ra đời và phát triển 6 | - Ý nghĩa và lợi ích của Design Pattern 7 | 8 | - [Chương 2: Nhóm Creational Patterns](docs/2.creational.md) 9 | - [Chương 2.1: Factory Method](docs/2.1.factory-method.md) 10 | - [Chương 2.2: Abstract Factory](docs/2.2.abstract-factory.md) 11 | - [Chương 2.3: Builder](docs/2.3.builder.md) 12 | - [Chương 2.4: Prototype](docs/2.4.prototype.md) 13 | - [Chương 2.5: Singleton](docs/2.5.singleton.md) 14 | 15 | - [Chương 3: Nhóm Structural Patterns](docs/3.structural.md) 16 | - [Chương 3.1: Adapter](docs/3.1.adapter.md) 17 | - [Chương 3.2: Bridge](docs/3.2.bridge.md) 18 | - [Chương 3.3: Composite](docs/3.3.composite.md) 19 | - [Chương 3.4: Decorator](docs/3.4.decorator.md) 20 | - [Chương 3.5: Facade](docs/3.5.facade.md) 21 | - [Chương 3.6: Flyweight](docs/3.6.flyweight.md) 22 | - [Chương 3.7: Proxy](docs/3.7.proxy.md) 23 | 24 | - [Chương 4: Nhóm Behavioral Patterns](docs/4.behavioral.md) 25 | - [Chương 4.1: Chain of Responsibility](docs/4.1.chain-of-responsibility.md) 26 | - [Chương 4.2: Command](docs/4.2.command.md) 27 | - [Chương 4.3: Iterator](docs/4.3.iterator.md) 28 | - [Chương 4.4: Mediator](docs/4.4.mediator.md) 29 | - [Chương 4.5: Memento](docs/4.5.memento.md) 30 | - [Chương 4.6: Observer](docs/4.6.observer.md) 31 | - [Chương 4.7: State](docs/4.7.state.md) 32 | - [Chương 4.8: Strategy](docs/4.8.strategy.md) 33 | - [Chương 4.9: Template Method](docs/4.9.template-method.md) 34 | - [Chương 4.10: Visitor](docs/4.10.visitor.md) 35 | 36 | - [Chương 5: Ứng dụng thực tế](docs/5.real-world.md) 37 | - [Kết luận](docs/conclusion.md) -------------------------------------------------------------------------------- /Writerside/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/Writerside/.DS_Store -------------------------------------------------------------------------------- /Writerside/c.list: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Writerside/cfg/buildprofiles.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | google-analytics-noscript.html 5 | 6 | 7 | -------------------------------------------------------------------------------- /Writerside/cfg/google-analytics-noscript.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | -------------------------------------------------------------------------------- /Writerside/hi.tree: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Writerside/images/completion_procedure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/Writerside/images/completion_procedure.png -------------------------------------------------------------------------------- /Writerside/images/completion_procedure_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/Writerside/images/completion_procedure_dark.png -------------------------------------------------------------------------------- /Writerside/images/convert_table_to_xml.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/Writerside/images/convert_table_to_xml.png -------------------------------------------------------------------------------- /Writerside/images/convert_table_to_xml_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/Writerside/images/convert_table_to_xml_dark.png -------------------------------------------------------------------------------- /Writerside/images/new_topic_options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/Writerside/images/new_topic_options.png -------------------------------------------------------------------------------- /Writerside/images/new_topic_options_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/Writerside/images/new_topic_options_dark.png -------------------------------------------------------------------------------- /Writerside/redirection-rules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | Created after removal of "Starter" from Help Instance 11 | Starter.html 12 | 13 | -------------------------------------------------------------------------------- /Writerside/topics/Abstract-Factory.md: -------------------------------------------------------------------------------- 1 | # Abstract Factory 2 | 3 | ## Giới thiệu 4 | 5 | Trong cuốn sách về Design Pattern, chúng ta đã tìm hiểu về nhóm Creational Pattern, bao gồm những Pattern giúp khởi tạo đối tượng một cách linh hoạt và thuận tiện. Factory Method là một Pattern đã được giới thiệu, giúp tạo ra các đối tượng của một lớp. Tuy nhiên, trong nhiều trường hợp, các đối tượng có quan hệ với nhau và được nhóm thành các họ. Lúc này, chúng ta cần Abstract Factory. 6 | 7 | Abstract Factory cung cấp một interface để tạo ra các họ đối tượng liên quan với nhau một cách linh hoạt. 8 | 9 | ## Đặt vấn đề 10 | 11 | Giả sử bạn đang phát triển một ứng dụng gọi món ăn cho nhà hàng. Các món ăn được phân thành các nhóm: 12 | 13 | - Món lẩu: Thịt bò, rau củ, nấm hương 14 | - Món phở: Bánh phở, thịt bò, giá đỗ 15 | - Món bún: Bún, nem nuong, chả giò 16 | 17 | Khi người dùng gọi món, các nguyên liệu cần được chuẩn bị phù hợp với nhau trong cùng một nhóm món. 18 | 19 | Ngoài ra, nhà hàng thường xuyên thay đổi thực đơn, bổ sung các nhóm món mới. 20 | 21 | Chúng ta cần một cách để dễ dàng tạo ra và thay đổi các nhóm món mà không ảnh hưởng đến code hiện tại. 22 | 23 | ## Giải quyết 24 | 25 | Để giải quyết vấn đề trên, Abstract Factory đưa ra ý tưởng: 26 | 27 | - Tạo interface định nghĩa các phương thức tạo các loại nguyên liệu trừu tượng: thịt, rau, carb, ... 28 | 29 | - Tạo các Concrete Factory triển khai interface này, mỗi Factory tương ứng với một nhóm món, chịu trách nhiệm tạo ra các nguyên liệu phù hợp. 30 | 31 | - Code sẽ sử dụng Abstract Factory để lấy các nguyên liệu một cách tổng quát. 32 | 33 | Như vậy, khi thêm nhóm món mới, chỉ cần tạo thêm Concrete Factory tương ứng, mà không làm ảnh hưởng code hiện tại. 34 | 35 | ## Cấu trúc 36 | 37 | Abstract Factory có cấu trúc gồm các thành phần chính sau: 38 | 39 | ```mermaid 40 | classDiagram 41 | 42 | class AbstractFactory { 43 | <> 44 | +CreateProductA() 45 | +CreateProductB() 46 | } 47 | 48 | AbstractFactory <|-- ConcreteFactory1 49 | AbstractFactory <|-- ConcreteFactory2 50 | 51 | ConcreteProductA1 --|> AbstractProductA 52 | ConcreteProductA2 --|> AbstractProductA 53 | 54 | ConcreteProductB1 --|> AbstractProductB 55 | ConcreteProductB2 --|> AbstractProductB 56 | 57 | 58 | ConcreteFactory1: +CreateProductA() 59 | ConcreteFactory1: +CreateProductB() 60 | 61 | ConcreteFactory2: +CreateProductA() 62 | ConcreteFactory2: +CreateProductB() 63 | 64 | Client --> AbstractFactory 65 | ConcreteFactory1 ..> ConcreteProductA1 66 | ConcreteFactory2 ..> ConcreteProductA2 67 | ConcreteFactory1 ..> ConcreteProductB1 68 | ConcreteFactory2 ..> ConcreteProductB2 69 | 70 | ``` 71 | 72 | - Abstract Factory interface: định nghĩa các phương thức nhà máy trừu tượng để tạo ra các sản phẩm trừu tượng. 73 | - Concrete Factory: cài đặt các phương thức nhà máy cụ thể để tạo ra các sản phẩm cụ thể. Mỗi Concrete Factory tạo ra một tập sản phẩm khác biệt, phù hợp với một variant. 74 | - Abstract Product: định nghĩa interface chung cho một loại sản phẩm trừu tượng. 75 | - Concrete Product: cài đặt các sản phẩm cụ thể, triển khai từ Abstract Product. Mỗi sản phẩm thuộc về một Concrete Factory nhất định. 76 | - Client: sử dụng Abstract Factory và Abstract Product để tương tác với hệ thống. Không cần quan tâm đến các lớp cụ thể. 77 | 78 | ## Cách triển khai 79 | 80 | Đầu tiên, ta định nghĩa interface AbstractFactory: 81 | ```java 82 | interface AbstractFactory { 83 | AbstractProductA createProductA(); 84 | AbstractProductB createProductB(); 85 | } 86 | ``` 87 | Tiếp theo, định nghĩa các Concrete Factory triển khai AbstractFactory: 88 | ```java 89 | class ConcreteFactory1 implements AbstractFactory { 90 | 91 | @Override 92 | AbstractProductA createProductA() { 93 | return new ConcreteProductA1(); 94 | } 95 | 96 | @Override 97 | AbstractProductB createProductB() { 98 | return new ConcreteProductB1(); 99 | } 100 | 101 | } 102 | 103 | class ConcreteFactory2 implements AbstractFactory { 104 | 105 | // implements createProductA() and createProductB() 106 | } 107 | ``` 108 | 109 | Định nghĩa các Abstract Product dưới dạng interface: 110 | 111 | ```java 112 | interface AbstractProductA {} 113 | interface AbstractProductB {} 114 | ``` 115 | 116 | Triển khai các Concrete Product từ Abstract Product: 117 | 118 | ```java 119 | class ConcreteProductA1 implements AbstractProductA {} 120 | 121 | class ConcreteProductB1 implements AbstractProductB {} 122 | ``` 123 | 124 | Cuối cùng, ở Client chúng ta sẽ sử dụng AbstractFactory để tạo ra các Abstract Product mà không cần quan tâm đến các lớp cụ thể: 125 | 126 | ```java 127 | public class Main { 128 | 129 | public static void main(String[] args) { 130 | 131 | // Khởi tạo factory 132 | AbstractFactory factory = new ConcreteFactory1(); 133 | 134 | // Sử dụng factory để lấy các sản phẩm 135 | AbstractProductA productA = factory.createProductA(); 136 | AbstractProductB productB = factory.createProductB(); 137 | 138 | // Sử dụng các sản phẩm 139 | productA.methodA(); 140 | productB.methodB(); 141 | 142 | // Thay đổi factory khác 143 | factory = new ConcreteFactory2(); 144 | 145 | // Lấy lại các sản phẩm 146 | productA = factory.createProductA(); 147 | productB = factory.createProductB(); 148 | 149 | // Sử dụng các sản phẩm mới 150 | } 151 | 152 | } 153 | ``` 154 | ## Ví dụ 155 | 156 | Dưới đây là một ví dụ minh họa về Abstract Factory trong Java: 157 | 158 | 159 | ```java 160 | // Interfaces cho các thành phần món ăn 161 | interface IProtein { 162 | public void prepare(); 163 | } 164 | 165 | interface ICarbohydrate { 166 | public void prepare(); 167 | } 168 | 169 | interface IVegetable { 170 | public void prepare(); 171 | } 172 | 173 | // Các thành phần cụ thể 174 | class Beef implements IProtein { 175 | public void prepare() { 176 | System.out.println("Preparing beef"); 177 | } 178 | } 179 | 180 | class RiceNoodle implements ICarbohydrate { 181 | public void prepare() { 182 | System.out.println("Preparing rice noodle"); 183 | } 184 | } 185 | 186 | // Các thành phần khác... 187 | 188 | // Abstract factory interface 189 | interface FoodFactory { 190 | public IProtein createProtein(); 191 | public ICarbohydrate createCarbohydrate(); 192 | public IVegetable createVegetable(); 193 | } 194 | 195 | // Concrete factory 196 | class LauFactory implements FoodFactory { 197 | 198 | @Override 199 | public IProtein createProtein() { 200 | return new Beef(); 201 | } 202 | 203 | @Override 204 | public ICarbohydrate createCarbohydrate() { 205 | return new RiceNoodle(); 206 | } 207 | 208 | @Override 209 | public IVegetable createVegetable() { 210 | return new Cabbage(); 211 | } 212 | } 213 | 214 | // Client 215 | public class Client { 216 | public static void main(String[] args) { 217 | FoodFactory factory = new LauFactory(); 218 | IProtein protein = factory.createProtein(); 219 | ICarbohydrate carb = factory.createCarbohydrate(); 220 | 221 | protein.prepare(); 222 | carb.prepare(); 223 | } 224 | } 225 | ``` 226 | Chương trình sẽ in ra các bước chuẩn bị cho từng thành phần món lẩu. Bạn có thể dễ dàng thêm các nhóm món khác bằng cách tạo thêm Concrete Factory. 227 | 228 | ## So sánh 229 | 230 | Abstract Factory có thể được so sánh với một số Design Pattern tương tự như: 231 | 232 | - Factory Method: Factory Method chỉ cung cấp phương thức factory để tạo ra đối tượng của một lớp cụ thể. Trong khi đó, Abstract Factory cung cấp interface để tạo ra toàn bộ họ các đối tượng liên quan. 233 | 234 | - Builder Pattern: Builder tập trung vào việc tạo ra một đối tượng phức tạp bằng cách tách quá trình xây dựng ra khỏi biểu diễn. Abstract Factory tập trung vào việc tạo ra các đối tượng thuộc cùng một họ liên quan. 235 | 236 | - Prototype Pattern: Prototype tạo ra đối tượng bằng cách clone đối tượng ban đầu. Abstract Factory tạo ra đối tượng mới mỗi lần được gọi. 237 | 238 | - Singleton Pattern: Singleton chỉ cho phép tồn tại duy nhất một instance. Abstract Factory tạo nhiều đối tượng khác nhau. 239 | 240 | ## Kết luận 241 | 242 | Abstract Factory là một Design Pattern hữu ích, có một số ưu điểm sau: 243 | 244 | - Tách biệt phần triển khai với phần sử dụng code, giảm sự phụ thuộc lẫn nhau giữa các đối tượng. 245 | 246 | - Có thể dễ dàng thay đổi, mở rộng cách tạo đối tượng mà không ảnh hưởng đến phần còn lại của code. 247 | 248 | - Giúp tạo ra các họ đối tượng liên quan một cách thống nhất. 249 | 250 | Tuy nhiên, Pattern cũng có một số nhược điểm cần lưu ý: 251 | 252 | - Cấu trúc phức tạp, nhiều lớp trừu tượng cần phải triển khai. 253 | 254 | - Khó khăn trong việc cân bằng giữa tính linh hoạt và hiệu suất. 255 | 256 | Vì vậy, Abstract Factory phù hợp trong trường hợp cần tạo ra các họ đối tượng liên quan, có tính mở rộng cao. Không nên sử dụng nếu chỉ cần tạo đơn giản một Object. 257 | 258 | Như vậy, với ưu điểm về tính linh hoạt và mở rộng, Abstract Factory là một Pattern rất hữu ích, phổ biến trong thiết kế phần mềm. -------------------------------------------------------------------------------- /Writerside/topics/Behavioral-Patterns.md: -------------------------------------------------------------------------------- 1 | # Behavioral Patterns 2 | 3 | Behavioral Patterns liên quan đến cách giao tiếp và trao đổi thông tin giữa các đối tượng và lớp. Các Pattern thuộc nhóm này gồm: 4 | 5 | ## [Chain of Responsibility](Chain-Of-Responsibility.md) 6 | 7 | Cho phép chuyển các yêu cầu dọc theo chuỗi các đối tượng xử lý. 8 | 9 | ## [Command](Command.md) 10 | Đóng gói yêu cầu thành các đối tượng có thể tham số hóa 11 | 12 | ## [Iterator](Iterator.md) 13 | 14 | Truy cập tuần tự các phần tử một tập hợp dữ liệu 15 | 16 | ## [Mediator](Mediator.md) 17 | 18 | Định nghĩa một đối tượng trung gian để giao tiếp giữa các đối tượng. 19 | 20 | ## [Memento](Memento.md) 21 | 22 | ## [Observer](Observer.md) 23 | 24 | Định nghĩa phụ thuộc một chiều giữa các đối tượng 25 | 26 | ## [State](State.md) 27 | 28 | Cho phép một đối tượng thay đổi hành vi dựa trên trang thái nội bộ 29 | 30 | ## [Strategy](Strategy.md) 31 | 32 | Định nghĩa tập các thuật toán có thể thay thế cho nhau để giải quyết một vấn đề. 33 | 34 | ## [Template Method](Template-Method.md) 35 | Định nghĩa bố cục xử lý chung cho một thuật toán, hoãn lại các bước cụ thể cho lớp con. 36 | 37 | ## [Visitor](Visitor.md) 38 | 39 | Tách biệt các thuật toán khởi các đối tượng mà chúng hoạt động trên đó. 40 | -------------------------------------------------------------------------------- /Writerside/topics/Bridge.md: -------------------------------------------------------------------------------- 1 | # Bridge 2 | 3 | ## Giới thiệu 4 | 5 | ### Định nghĩa Pattern 6 | 7 | Bridge Pattern là một mẫu thiết kế thuộc loại cấu trúc. Nó giúp tách rời abstraction (lớp trừu tượng) và implementation (lớp thực thi) ra khỏi nhau, giúp cả hai có thể thay đổi và phát triển một cách độc lập, không làm ảnh hưởng đến nhau. 8 | 9 | ### Mục đích 10 | 11 | - Tách biệt abstraction khỏi implementation để cả hai có thể thay đổi mà không ảnh hưởng đến nhau. 12 | - Khắc phục vấn đề kết hợp giữa lớp cha và lớp con, giúp giảm sự phức tạp trong thiết kế và giúp mở rộng mã nguồn một cách linh hoạt hơn. 13 | - Cung cấp khả năng thay thế và tái sử dụng implementation mà không cần sửa đổi code của lớp trừu tượng. 14 | 15 | ### Ý tưởng chính của Pattern 16 | 17 | Ý tưởng chính của Bridge Pattern là sử dụng "cầu nối" giữa abstraction và implementation. Thay vì một lớp trừu tượng kiểm soát và mở rộng từ một lớp cụ thể (lớp thực thi), mẫu thiết kế này đề xuất việc tạo ra một interface (cầu nối) giữa chúng. Khi cần mở rộng chức năng, bạn có thể thêm vào phía abstraction mà không ảnh hưởng đến phía implementation và ngược lại. Nhờ có "cầu nối" này, việc thay đổi và phát triển mã nguồn trở nên linh hoạt và ít gặp rủi ro hơn. 18 | 19 | ## Đặt vấn đề 20 | 21 | Hãy tưởng tượng bạn có một lớp `Vehicle` với hai subclass là `BicycleBike` và `MotorBike`. Bây giờ, bạn muốn mở rộng tính năng bằng cách thêm màu sắc cho mỗi loại phương tiện, và bạn tạo ra hai thuộc tính là `Red` và `Blue`. Với cách tiếp cận này, bạn sẽ phải tạo ra tổng cộng bốn lớp con như `BlueBicycleBike` và `RedMotorBike`. 22 | 23 | ```mermaid 24 | classDiagram 25 | class Vehicle { 26 | } 27 | 28 | class BicycleBike { 29 | } 30 | class MotorBike { 31 | } 32 | 33 | class Red { 34 | } 35 | class Blue { 36 | } 37 | 38 | class BlueBicycleBike { 39 | } 40 | class RedBicycleBike { 41 | } 42 | class BlueMotorBike { 43 | } 44 | class RedMotorBike { 45 | } 46 | 47 | Vehicle <|-- BicycleBike 48 | Vehicle <|-- MotorBike 49 | 50 | BicycleBike <|-- BlueBicycleBike 51 | BicycleBike <|-- RedBicycleBike 52 | MotorBike <|-- BlueMotorBike 53 | MotorBike <|-- RedMotorBike 54 | 55 | Red <--o BlueBicycleBike 56 | Red <--o RedBicycleBike 57 | Blue <--o BlueMotorBike 58 | Blue <--o RedMotorBike 59 | 60 | ``` 61 | 62 | Khi bạn muốn thêm một loại phương tiện hoặc một màu sắc mới, bạn sẽ cần tạo thêm nhiều lớp con, làm cho hệ thống trở nên phức tạp và khó kiểm soát. 63 | 64 | ## Giải pháp 65 | 66 | Vấn đề ở đây là chúng ta đang cố gắng tích hợp quá nhiều tính năng vào một lớp trừu tượng, trong khi mỗi tính năng đều có tiềm năng phát triển theo hướng riêng biệt. 67 | 68 | ```mermaid 69 | classDiagram 70 | class Vehicle { 71 | +Color color 72 | +void manage() 73 | } 74 | 75 | class Color { 76 | +void bePainted() 77 | } 78 | 79 | class BicycleBike { 80 | +void manage() 81 | } 82 | 83 | class MotorBike { 84 | +void manage() 85 | } 86 | 87 | class Red { 88 | +void bePainted() 89 | } 90 | 91 | class Blue { 92 | +void bePainted() 93 | } 94 | 95 | Vehicle <|-- BicycleBike: is a 96 | Vehicle <|-- MotorBike: is a 97 | Vehicle "1" *-- "1" Color: has a 98 | Color <|-- Red: is a 99 | Color <|-- Blue: is a 100 | ``` 101 | 102 | Bridge Pattern giải quyết vấn đề này bằng cách tách biệt lớp trừu tượng (abstraction) và các đối tượng thực thi (implementation), sau đó kết nối chúng lại với nhau thông qua một "cầu" (bridge). Trong ví dụ này, một phương tiện sẽ có một thuộc tính màu sắc, tạo ra mối quan hệ "has-a" (có một) thay vì "is-a" (là một). 103 | 104 | ## Cấu Trúc 105 | 106 | ```mermaid 107 | classDiagram 108 | class Abstraction { 109 | +Implementor implementor 110 | +operation() void 111 | } 112 | 113 | class Implementor { 114 | +operationImpl() void 115 | } 116 | 117 | class ConcreteImplementorA { 118 | +operationImpl() void 119 | } 120 | 121 | class ConcreteImplementorB { 122 | +operationImpl() void 123 | } 124 | 125 | class RefinedAbstraction { 126 | +operation() void 127 | } 128 | 129 | Abstraction <|-- RefinedAbstraction: is a 130 | Abstraction "1" *-- "1" Implementor: has a 131 | Implementor <|-- ConcreteImplementorA: is a 132 | Implementor <|-- ConcreteImplementorB: is a 133 | ``` 134 | 135 | 1. **The Abstraction** (`Abstraction`): Lớp cơ sở cung cấp mức độ trừu tượng cho việc quản lý các công việc do các đối tượng cụ thể thực hiện (Implementation). 136 | 2. **The Implementation** (`Implementor`): Giao diện định nghĩa các tác vụ cần thiết cho lớp trừu tượng. Đây thường là một giao diện xác định các tác vụ cần thiết cho lớp trừu tượng. 137 | 3. **Concrete Implementations** (`ConcreteImplementor`): Các lớp này chứa logic cụ thể và thực hiện các tác vụ được định nghĩa bởi `Implementor`. 138 | 4. **Refined Abstractions** (`RefinedAbstraction`): Các lớp con của `Abstraction` thực hiện và mở rộng các phương thức được xác định trong lớp `Abstraction`. 139 | 140 | ## Cách triển khai 141 | 142 | 143 | ### Bước 1: Xác định Abstraction và Implementation 144 | 145 | Đầu tiên, ta cần phân biệt giữa abstractions (trừu tượng) và implementations (thực thi). 146 | 147 | ```java 148 | // Abstraction 149 | public abstract class Shape { 150 | protected Color color; 151 | 152 | public Shape(Color color) { 153 | this.color = color; 154 | } 155 | 156 | public abstract void draw(); 157 | } 158 | 159 | // Implementation 160 | public interface Color { 161 | void applyColor(); 162 | } 163 | ``` 164 | 165 | ### Bước 2: Mở rộng Abstraction 166 | 167 | Chúng ta có thể mở rộng abstraction để tạo ra các phân lớp khác nhau. 168 | 169 | ```java 170 | public class Circle extends Shape { 171 | public Circle(Color color) { 172 | super(color); 173 | } 174 | 175 | @Override 176 | public void draw() { 177 | System.out.print("Draw Circle in "); 178 | color.applyColor(); 179 | } 180 | } 181 | 182 | public class Square extends Shape { 183 | public Square(Color color) { 184 | super(color); 185 | } 186 | 187 | @Override 188 | public void draw() { 189 | System.out.print("Draw Square in "); 190 | color.applyColor(); 191 | } 192 | } 193 | ``` 194 | 195 | ### Bước 3: Cung cấp các Implementations cụ thể 196 | 197 | ```java 198 | public class RedColor implements Color { 199 | @Override 200 | public void applyColor() { 201 | System.out.println("Red color."); 202 | } 203 | } 204 | 205 | public class BlueColor implements Color { 206 | @Override 207 | public void applyColor() { 208 | System.out.println("Blue color."); 209 | } 210 | } 211 | ``` 212 | 213 | ### Bước 4: Sử dụng Bridge Pattern 214 | 215 | ```java 216 | public class BridgePatternDemo { 217 | public static void main(String[] args) { 218 | Shape redCircle = new Circle(new RedColor()); 219 | Shape blueSquare = new Square(new BlueColor()); 220 | 221 | redCircle.draw(); 222 | blueSquare.draw(); 223 | } 224 | } 225 | ``` 226 | 227 | Khi chạy đoạn mã trên, kết quả sẽ là: 228 | ``` 229 | Draw Circle in Red color. 230 | Draw Square in Blue color. 231 | ``` 232 | 233 | ## Ví dụ áp dụng Bridge Pattern 234 | 235 | Để hiểu rõ hơn về cách Bridge Pattern hoạt động, hãy xem xét ví dụ về một hệ thống ngân hàng cung cấp các loại tài khoản khác nhau: 236 | 237 | **Account.java** 238 | ```java 239 | public interface Account { 240 | void openAccount(); 241 | } 242 | ``` 243 | 244 | **CheckingAccount.java** 245 | ```java 246 | public class CheckingAccount implements Account{ 247 | @Override 248 | public void openAccount() { 249 | System.out.println("Opening a Checking Account!"); 250 | } 251 | } 252 | ``` 253 | 254 | **TutorialAccount.java** 255 | ```java 256 | public class TutorialAccount implements Account{ 257 | @Override 258 | public void openAccount() { 259 | System.out.println("Please select your language"); 260 | } 261 | } 262 | ``` 263 | 264 | **Bank.java** 265 | ```java 266 | public abstract class Bank { 267 | protected Account account; 268 | 269 | public Bank(Account account) { 270 | this.account = account; 271 | } 272 | 273 | public abstract void openAccount(); 274 | } 275 | ``` 276 | 277 | **MMBank.java** 278 | ```java 279 | public class MMBank extends Bank { 280 | 281 | public MMBank(Account account) { 282 | super(account); 283 | } 284 | 285 | @Override 286 | public void openAccount() { 287 | System.out.println("Welcome to MMBank"); 288 | account.openAccount(); 289 | } 290 | } 291 | ``` 292 | 293 | **TPBank.java** 294 | ```java 295 | public class TPBank 296 | 297 | extends Bank { 298 | 299 | public TPBank(Account account) { 300 | super(account); 301 | } 302 | 303 | @Override 304 | public void openAccount() { 305 | System.out.println("Welcome to TPBank"); 306 | account.openAccount(); 307 | } 308 | } 309 | ``` 310 | 311 | **demo.java** 312 | ```java 313 | public class demo { 314 | public static void main(String[] args) { 315 | Bank tpBank = new TPBank(new TutorialAccount()); 316 | tpBank.openAccount(); 317 | 318 | System.out.println(); 319 | 320 | Bank mmBank = new MMBank(new CheckingAccount()); 321 | mmBank.openAccount(); 322 | } 323 | } 324 | ``` 325 | 326 | Kết quả khi chạy chương trình: 327 | 328 | ``` 329 | Welcome to TPBank 330 | Please select your language 331 | 332 | Welcome to MMBank 333 | Opening a Checking Account! 334 | ``` 335 | 336 | Như bạn thấy trong ví dụ trên, `Bank` là một lớp trừu tượng kết hợp với interface `Account`. Các lớp cụ thể như `TPBank` và `MMBank` kế thừa từ lớp `Bank` và quyết định cách họ muốn mở tài khoản dựa trên loại tài khoản cụ thể (như `CheckingAccount` hoặc `TutorialAccount`). Nhờ sử dụng Bridge Pattern, chúng ta có thể mở rộng cả hai hệ thống (loại ngân hàng và loại tài khoản) một cách độc lập mà không làm ảnh hưởng đến nhau. 337 | 338 | ## So sánh 339 | 340 | ### 1. Bridge vs Adapter: 341 | 342 | - **Bridge**: Như chúng ta đã biết, mục tiêu chính của Bridge Pattern là tách rời abstraction (trừu tượng) ra khỏi implementation (thực thi) của nó, giúp cho cả hai có thể thay đổi độc lập. 343 | - **Adapter**: Mẫu thiết kế này cho phép các đối tượng với interfaces không tương thích có thể làm việc cùng nhau thông qua một lớp trung gian. 344 | 345 | ### 2. Bridge vs Composite: 346 | 347 | - **Bridge**: Tách rời abstraction và implementation để chúng phát triển độc lập. 348 | - **Composite**: Cung cấp một cách để bạn có thể làm việc với các đối tượng đơn lẻ hoặc với nhóm các đối tượng theo cùng một cách. 349 | 350 | ### 3. Bridge vs Decorator: 351 | 352 | - **Bridge**: Phân tách interface (trừu tượng) và thực thi, cho phép chúng thay đổi độc lập. 353 | - **Decorator**: Thêm các trách nhiệm cho đối tượng mà không cần sửa đổi chúng, giữ nguyên interface của đối tượng và thêm chức năng mở rộng. 354 | 355 | ### 4. Bridge vs Facade: 356 | 357 | - **Bridge**: Đảm bảo tính linh hoạt giữa abstraction và implementation bằng cách tách chúng ra. 358 | - **Facade**: Cung cấp một giao diện đơn giản hoá cho một hệ thống con, giúp giảm sự phức tạp khi giao tiếp với các hệ thống phức tạp. 359 | 360 | ### 5. Bridge vs Proxy: 361 | 362 | - **Bridge**: Tập trung vào việc tách rời và linh hoạt giữa abstractions và implementations. 363 | - **Proxy**: Cung cấp một đại diện cho một đối tượng khác, kiểm soát việc truy cập đến đối tượng gốc. 364 | 365 | ## Kết luận 366 | 367 | Bridge Pattern là một mẫu thiết kế hiệu quả giúp tách rời các khía cạnh trừu tượng và thực thi của một lớp, giúp chúng có thể thay đổi và phát triển một cách độc lập. Điều này không chỉ giúp giảm thiểu sự phức tạp khi mở rộng hệ thống mà còn cung cấp khả năng linh hoạt hơn trong việc quản lý và mở rộng code. -------------------------------------------------------------------------------- /Writerside/topics/Composite.md: -------------------------------------------------------------------------------- 1 | # Composite 2 | 3 | ## Giới thiệu 4 | 5 | ### Định nghĩa Pattern 6 | Composite Pattern là một mẫu thiết kế thuộc nhóm cấu trúc, được sử dụng để tổ chức các đối tượng vào một cấu trúc cây. Mẫu thiết kế này tạo ra một hệ thống phân cấp cho phép người dùng xử lý các đối tượng đơn lẻ và tổ hợp của chúng một cách thống nhất. 7 | 8 | ### Mục đích 9 | Mục đích chính của Composite Pattern là đơn giản hóa quá trình làm việc với các cấu trúc phức tạp bằng cách cho phép client tương tác với các đối tượng đơn lẻ và tổ hợp theo cùng một cách. Điều này giúp giảm thiểu sự phức tạp khi quản lý và tương tác với cấu trúc cây, làm cho mã nguồn dễ bảo trì và mở rộng hơn. 10 | 11 | ### Ý tưởng chính của Pattern 12 | Ý tưởng cốt lõi của Composite Pattern nằm ở việc cung cấp một interface chung cho cả hai loại đối tượng: đơn lẻ và tổ hợp. Interface này cho phép client tương tác với mỗi đối tượng một cách riêng lẻ hoặc nhóm các đối tượng lại với nhau như một thể thống nhất mà không cần quan tâm đến đặc điểm nội tại của chúng. Kết quả là, client có thể thêm, xóa hoặc thay đổi các đối tượng trong cấu trúc cây một cách linh hoạt mà không cần viết lại code hoặc hiểu biết sâu sắc về cấu trúc nội bộ. 13 | 14 | ## Đặt vấn đề 15 | 16 | Khi sử Composite Pattern bạn phải chắc chắn rằng mô hình ứng dụng của bạn có thể biểu hiện bằng sơ đồ cây. 17 | 18 | Ví dụ như sau: Trong việc lưu trữ trong máy tính có hai dạng chính: `Folder` và `File`. Một `Folder` thì có thể chứa nhiều `Folder` và `File`. Có thể một trong `Folder` chỉ chứa `File` và trong `File` thì chứa nội dụng. 19 | 20 | ```mermaid 21 | graph TB 22 | id1(Folder) 23 | id2(Folder) 24 | id3(Folder) 25 | id4(File) 26 | id5(File) 27 | id6(File) 28 | id7(File) 29 | id1 --> id2 30 | id1 --> id3 31 | id1 --> id4 32 | id2 --> id5 33 | id3 --> id6 34 | id3 --> id7 35 | 36 | subgraph traditional_approach 37 | id1 --> id2 38 | id2 --> id5 39 | id1 --> id4 40 | id1 --> id3 41 | id3 --> id6 42 | id3 --> id7 43 | end 44 | ``` 45 | 46 | Giờ giả sử ta cần tìm tất cả File trong một Folder. Thử cách tiếp cận thông thường là ta sẽ mở từng Folder con ra và đếm xem co bao nhiêu File vào Folder tiếp theo đếm tiếp. Nhưng trong lập trình nó không hề đơn giản như việc bạn chỉ cần chạy một dòng for. Bạn phải biết trước loại File và Folder mà sẽ duyệt và mực đồ lòng vào nhau. Tất cả điều đó làm cho cách tiếp cận này trở nên khó khăn hơn. 47 | 48 | ## Giải pháp 49 | 50 | Chúng ta sẽ sử chung Composite Pattern để thực hiện công việc với Folder và File bằng cách tạo một interrface chung với một phương thức count(Đếm) 51 | 52 | ```mermaid 53 | classDiagram 54 | class Component { 55 | +count() int 56 | } 57 | 58 | class File { 59 | +count() int 60 | } 61 | 62 | class Folder { 63 | +List~Component~ children 64 | +count() int 65 | +add(component Component) void 66 | +remove(component Component) void 67 | } 68 | 69 | Component <|-- File: is a 70 | Component <|-- Folder: is a 71 | Folder "1" *-- "*" Component: contains 72 | ``` 73 | 74 | Cái này hoạt động như sau. Đối với File thì chỉ trả về cộng một, Đối với Folder thì nó sẽ duyệt từng item trong Folder đó, bắt từng item đếm sau cùng tới lượt nó tổng hợp lại và trả về tổng số của Folder. Nếu một các item là Folder thì sao? Thì nó sẽ bắt Folder con đó đi đếm các thành item nằm trong Folder con và trả về tổng số. 75 | 76 | Nói đến đây các bạn sẽ nói, ô đây là "Rùa Em" (Đệ Quy). Nhưng với Composite nó sẽ có hiệu quả gì ? Nó sẽ giúp bạn làm việc với các thành phần một cách dể dàng, chỉ cần thông qua interface mà không phải xử lý rác rối sâu đến bên trong. Nhưng lời kêu gọi của bạn sẽ được xử lý chạy dần xuống theo cấu trúc cây. 77 | 78 | ## Cấu Trúc 79 | 80 | ```mermaid 81 | classDiagram 82 | class Component { 83 | +operation() 84 | } 85 | 86 | class Leaf { 87 | +operation() 88 | } 89 | 90 | class Composite { 91 | -children List 92 | +operation() 93 | +add(Component) 94 | +remove(Component) 95 | +getChild(int) 96 | } 97 | 98 | Component <|-- Leaf : Is a 99 | Component <|-- Composite : Is a 100 | Composite "1" *-- "many" Component : Contains 101 | 102 | class Component { 103 | <> 104 | +operation() 105 | } 106 | ``` 107 | 108 | - **Component**: interface chung, mô ta các phương thức chung của thành phần trong cây. 109 | - **Leaf**: Đây là thành phần cơ bản của cây, nó không có các node con. 110 | - **Composite**: lưu trữ tập hợp các Leaf và cài đặt các phương thức của Component. 111 | 112 | ## Cách triển khai 113 | 114 | ### **Bước 1: Xây dựng Component** 115 | 116 | ```java 117 | public abstract class Component { 118 | protected String name; 119 | 120 | public Component(String name) { 121 | this.name = name; 122 | } 123 | 124 | public abstract void add(Component component); 125 | public abstract void remove(Component component); 126 | public abstract void display(int depth); 127 | } 128 | ``` 129 | 130 | ### **Bước 2: Xây dựng Leaf** 131 | 132 | ```java 133 | public class Leaf extends Component { 134 | public Leaf(String name) { 135 | super(name); 136 | } 137 | 138 | @Override 139 | public void add(Component component) { 140 | // Không thực hiện bất cứ điều gì 141 | } 142 | 143 | @Override 144 | public void remove(Component component) { 145 | // Không thực hiện bất cứ điều gì 146 | } 147 | 148 | @Override 149 | public void display(int depth) { 150 | System.out.println("-".repeat(depth) + name); 151 | } 152 | } 153 | ``` 154 | 155 | ### **Bước 3: Xây dựng Composite** 156 | 157 | ```java 158 | import java.util.ArrayList; 159 | import java.util.List; 160 | 161 | public class Composite extends Component { 162 | private List children = new ArrayList<>(); 163 | 164 | public Composite(String name) { 165 | super(name); 166 | } 167 | 168 | @Override 169 | public void add(Component component) { 170 | children.add(component); 171 | } 172 | 173 | @Override 174 | public void remove(Component component) { 175 | children.remove(component); 176 | } 177 | 178 | @Override 179 | public void display(int depth) { 180 | System.out.println("-".repeat(depth) + name); 181 | for (Component component : children) { 182 | component.display(depth + 2); 183 | } 184 | } 185 | } 186 | ``` 187 | 188 | ### **Bước 4: Sử dụng mẫu Composite** 189 | 190 | ```java 191 | public class Client { 192 | public static void main(String[] args) { 193 | Composite root = new Composite("root"); 194 | root.add(new Leaf("Leaf A")); 195 | root.add(new Leaf("Leaf B")); 196 | 197 | Composite comp = new Composite("Composite X"); 198 | comp.add(new Leaf("Leaf XA")); 199 | comp.add(new Leaf("Leaf XB")); 200 | 201 | root.add(comp); 202 | 203 | root.display(1); 204 | } 205 | } 206 | ``` 207 | 208 | Kết quả: 209 | 210 | ``` 211 | -root 212 | --Leaf A 213 | --Leaf B 214 | --Composite X 215 | ---Leaf XA 216 | ---Leaf XB 217 | ``` 218 | 219 | ## Ví dụ áp dụng Composite Pattern 220 | 221 | 222 | Chúng ta làm ví dụ ở trên nhưng thay đối một ít là ta sẽ xem tổng folder có size bao nhiêu 223 | 224 | FileComponent.kt 225 | 226 | ```kotlin 227 | interface FileComponent { 228 | fun showProperty() 229 | fun size() : Long 230 | } 231 | ``` 232 | 233 | FileLeaf.kt 234 | 235 | ```kotlin 236 | class FileLeaf : FileComponent { 237 | 238 | private var name:String 239 | private var size:Long 240 | 241 | constructor(name: String, size: Long) { 242 | this.name = name 243 | this.size = size 244 | } 245 | 246 | 247 | override fun showProperty() { 248 | System.out.println(this.name) 249 | } 250 | 251 | override fun size(): Long { 252 | return size; 253 | } 254 | } 255 | ``` 256 | 257 | FolderComposite.kt 258 | 259 | ```kotlin 260 | class FolderComposite : FileComponent{ 261 | 262 | private var files: List 263 | 264 | constructor(files: List) { 265 | this.files = files 266 | } 267 | 268 | override fun showProperty() { 269 | for (file in this.files) 270 | { 271 | file.showProperty() 272 | } 273 | 274 | } 275 | 276 | override fun size(): Long { 277 | var total : Long = 0 278 | for (file in this.files) { 279 | total += file.size() 280 | } 281 | return total 282 | } 283 | 284 | } 285 | ``` 286 | 287 | Kết quả 288 | 289 | ``` 290 | file 1 291 | file 2 292 | file 3 293 | Total Size: 27 294 | ``` 295 | 296 | ## So sánh Composite Pattern 297 | 298 | ### 1. Composite vs Adapter: 299 | 300 | - **Composite**: Được sử dụng để biểu diễn và quản lý một nhóm đối tượng như một đối tượng đơn lẻ. 301 | - **Adapter**: Được sử dụng để cho phép hai interfaces không tương thích có thể làm việc cùng nhau mà không cần phải sửa đổi bất kỳ lớp nào. 302 | 303 | ### 2. Composite vs Decorator: 304 | 305 | - **Composite**: Tập trung vào việc tạo ra cấu trúc dạng cây, nơi một nhóm đối tượng và đối tượng đơn lẻ có thể được xử lý theo cùng một cách. 306 | - **Decorator**: Mục tiêu là mở rộng chức năng của một đối tượng mà không cần sửa đổi chúng. 307 | 308 | ### 3. Composite vs Facade: 309 | 310 | - **Composite**: Xây dựng một cấu trúc dạng cây và làm việc với một nhóm đối tượng giống như một đối tượng duy nhất. 311 | - **Facade**: Cung cấp một giao diện đơn giản hoá cho một hệ thống phức tạp, giúp giảm sự phức tạp của việc gọi đến các API hoặc hệ thống phức tạp. 312 | 313 | ### 4. Composite vs Proxy: 314 | 315 | - **Composite**: Biểu diễn và quản lý một nhóm đối tượng dưới dạng cấu trúc cây. 316 | - **Proxy**: Đại diện cho một đối tượng khác và kiểm soát việc truy cập đến đối tượng đó, thường được sử dụng để điều khiển quyền truy cập hoặc tối ưu hóa việc tạo đối tượng. 317 | 318 | ### Kết luận 319 | 320 | Composite Pattern là một mẫu thiết kế hữu ích để xây dựng và quản lý cấu trúc phân cấp dưới dạng cây của các đối tượng. Nó cho phép chúng ta làm việc với một nhóm đối tượng như một đối tượng đơn lẻ, mang lại khả năng tổ chức và quản lý phân cấp một cách linh hoạt và thuận tiện. 321 | 322 | #### Ưu điểm: 323 | - **Tích hợp Mạnh**: Composite Pattern giúp tích hợp các đối tượng vào một cấu trúc dạng cây một cách dễ dàng. 324 | - **Linh Hoạt**: Cho phép bạn thêm, xóa hoặc sửa đổi các đối tượng trong cấu trúc một cách linh hoạt mà không làm ảnh hưởng đến toàn bộ cấu trúc. 325 | - **Tính Nhất quán**: Cấu trúc được xây dựng dưới dạng cây giúp việc làm việc với đối tượng đơn lẻ và nhóm đối tượng trở nên nhất quán. 326 | 327 | #### Nhược điểm: 328 | - **Quá mức Tổng quát**: Có thể tạo ra quá nhiều lớp và đối tượng nếu mẫu được sử dụng không cẩn thận. 329 | 330 | #### Hướng dẫn sử dụng: 331 | - **Nên sử dụng khi**: 332 | - Bạn muốn biểu diễn và quản lý một nhóm đối tượng dưới dạng cấu trúc cây. 333 | - Cần làm việc với các đối tượng và nhóm đối tượng theo cùng một cách. 334 | - Muốn cung cấp một giao diện chung cho cả đối tượng đơn lẻ và nhóm đối tượng. 335 | 336 | - **Không nên sử dụng khi**: 337 | - Không có nhu cầu xây dựng cấu trúc dạng cây hoặc quản lý các đối tượng dưới dạng phân cấp. 338 | - Cấu trúc dạng cây có thể trở nên quá phức tạp và không cần thiết cho ứng dụng của bạn. 339 | -------------------------------------------------------------------------------- /Writerside/topics/Creational-Patterns.md: -------------------------------------------------------------------------------- 1 | # Creational Patterns 2 | 3 | Creational Patterns cung cấp các giải pháp khởi tao đối tượng một cách linh hoạt và phù hợp với bối cảnh sử dụng. Các Pattern thuộc nhóm này gồm: 4 | 5 | ## [Singleton](Singleton.md) 6 | 7 | Đảm bảo chỉ có duy nhất một instance của một class trong toàn bộ chương trình. 8 | 9 | ## [Factory Method](Factory-Method.md) 10 | 11 | Định nghĩa một interface để tạo các đối tượng trong superclass nhưng cho phép lớp con quyết định instance nào sẽ được tạo. 12 | 13 | ## [Abstract Factory](Abstract-Factory.md) 14 | 15 | Cung cấp một interface để tạo ra các họ đối tượng liên quan hoặc phụ thuộc lẫn nhau. 16 | 17 | ## [Builder](Builder.md) 18 | 19 | Tách biệt quá trình khởi tạo đối tượng phức tạp khởi các đại diện của nó 20 | 21 | ## [Prototype](Prototype.md) 22 | 23 | Tạo ra các đối tượng dựa trên một mẫu đối tượng ban đầu 24 | 25 | Các Pattern này giải quyết vấn đề khởi tạo đối tượng một cách linh hoạt, thay vì khởi tạo trực tiếp bằng từ khóa new. Giúp tăng tính mềm dẻo và tái sử dụng code. -------------------------------------------------------------------------------- /Writerside/topics/Intro.md: -------------------------------------------------------------------------------- 1 | # Giới thiệu Design Pattern 2 | 3 | ## Định nghĩa Design Pattern 4 | 5 | Design Pattern là một mô hình thiết kế được sử dụng để giải quyết một vấn đề cụ thể trong lập trình. Nó cung cấp một giải pháp đã được kiểm nghiệm và tối ưu hóa, giúp các lập trình viên tiết kiệm thời gian và công sức khi phát triển phần mềm 6 | 7 | ## Lịch sử ra đời và phát triển 8 | 9 | Design Pattern được khai sinh vào những năm 1970 với sự phát triển của lập trình hướng đối tượng (OOP). Kể từ đó, nó đã trở thành một phần quan trọng trong quá trình phát triển phần mềm. 10 | 11 | Năm 1994, ba lập trình viên Erich Gamma, Richard Helm, Ralph Johnson và John Vlissides đã xuất bản cuốn sách "Design Patterns: Elements Of Resuable Object - Oriented Software". Cuốn sách này đã trở thành một trong những tài liệu tham khảo quan trọng nhất về Design Pattern. 12 | 13 | Trong những năm gần đây, Design Pattern tiếp tục được phát triển và mở rộng. Ngày càng có nhiều Design Pattern mới được giới thiệu, phù hợp với các yêu cầu mới của lâp trình. 14 | 15 | ## Ý nghĩa và lợi ích của Design Pattern 16 | 17 | Design Pattern mang lại nhiều ý nghĩa và lợi ích cho lập trình, bao gồm: 18 | 19 | - **Giúp giải quyết vấn đề một cách hiệu quả và tối ưu:** Design Pattern cung cấp các giải pháp đã được kiểm nghiệm và tối ưu hóa, giúp các lập trình viên giải quyết các vấn đề một cách nhanh chóng và hiêu quả. 20 | - **Tăng tính tái sử dụng của code:** Design Pattern giúp các lập trình viên tái sử dụng code đã có, từ đó giảm thiểu thời gian và công ức phát triển phần mềm. 21 | - **Tăng tính bảo trì và bảo dưỡng của phần mềm:** Design Pattern giúp phần mềm dễ dàng bảo trì và bảo dưỡng hơn. 22 | - **Tăng tính dể hiểu và dễ đọc của code:** Design Pattern giúp code dễ hiểu và dễ đọc hơn, giúp việc công tác giữa các lập trình viên trở nên dễ dàng hơn. 23 | 24 | Design Pattern là một kỹ thuật nâng cao của OOP, nó cực kì quan trọng trong lập trình. Nó mang lại nhiều ý nghĩa và lợi ích cho lập trình, giúp các lập trình viên phát triển phần mềm hiệu quả hơn. 25 | 26 | # 2. Phân loại Design Pattern 27 | 28 | ## Creational Design Patterns 29 | 30 | Creational Design Patterns liên quan tới việc khởi tạo đối tượng. Nhóm pattern này cung cấp các cơ chế tạo đối tượng một cách linh hoạt và phù hợp với bối cảnh sử dụng. Một số pattern phổ biến: 31 | 32 | [Singleton](Singleton.md) 33 | 34 | [Factory Method](Factory-Method.md) 35 | 36 | [Abstract Factory](Abstract-Factory.md) 37 | 38 | [Builder](Builder.md) 39 | 40 | [Prototype](Prototype.md) 41 | 42 | Sử dụng Creational Patterns giúp tạo ra các đối tượng một cách linh hoạt, dễ dàng thay đổi và tối ưu hóa bộ nhớ. 43 | ## Structural Design Patterns 44 | 45 | Structural Patterns liên quan tới cấu trúc và mối quan hệ giữa các lớp, đối tượng. Nhóm này giúp xây dựng cấu trúc phần mềm dễ thay đổi và bảo trì. Một số pattern: 46 | 47 | [Adapter](Adapter.md) 48 | 49 | [Bridge](Bridge.md) 50 | 51 | [Composite](Composite.md) 52 | 53 | [Decorator](Decorator.md) 54 | 55 | [Facade](Facade.md) 56 | 57 | [Flyweight](Flyweight.md) 58 | 59 | [Proxy](Proxy.md) 60 | 61 | Sử dụng Structural Patterns giúp xây dựng hệ thống linh hoạt, dễ mở rộng và tối ưu hóa bộ nhớ. 62 | 63 | ## Behavioral Design Patterns 64 | 65 | Behavioral Patterns liên quan tới hành vi giao tiếp giữa các đối tượng. Nhóm này giúp định nghĩa rõ ràng mối quan hệ giữa các object. Một số pattern: 66 | 67 | [Chain of Responsibility](Chain-Of-Responsibility.md) 68 | 69 | [Command](Command.md) 70 | 71 | [Iterator](Iterator.md) 72 | 73 | [Mediator](Mediator.md) 74 | 75 | [Memento](Memento.md) 76 | 77 | [Observer](Observer.md) 78 | 79 | [State](State.md) 80 | 81 | [Strategy](Strategy.md) 82 | 83 | [Template Method](Template-Method.md) 84 | 85 | [Visitor](Visitor.md) 86 | 87 | Sử dụng Behavioral Patterns giúp tạo hệ thống linh hoạt, dễ thay đổi và tối ưu hóa hiệu suất. 88 | 89 | # 3. Sử dụng Design Pattern 90 | 91 | ## Nguyên tắc và phương pháp áp dụng Design Pattern 92 | 93 | ### Nguyên Tắc 94 | 95 | Để áp dụng Design Pattern hiệu quả, các lập trinh viên cần nắm được các nguyên tắc và phương pháp sau đây: 96 | 97 | - **Nguyên tắc đầu tiên là phải hiểu rõ vấn đề cần giải quyết:** Trước khi áp dụng Design Pattern, các lập trinh viên cần hiểu rõ vấn đề cần giải quyết là gì. Từ đó, họ có thể lựa chọn được Design Pattern phù hợp nhất. 98 | 99 | - **Nguyên tắc thứ hai là phải hiểu rõ Design Pattern:** Các lập trình viên cần hiểu rõ bản chất và cách hoạt động của Design Pattern. Từ đó, họ có thể áp dụng Design Pattern một cách chính xác và hiệu quả. 100 | 101 | - **Nguyên tắc thứ ba là phải linh hoạt trong việc áp dụng Design Pattern:** Không phải lúc nào cũng có thể áp dụng Design Pattern một cách cứng nhắc. Các lập trình viên cần linh hoạt trong việc áp dụng Design Pattern để phù hợp với nhu cầu cụ thể của dự án. 102 | 103 | ### Phương pháp 104 | 105 | - **Phương pháp trực tiếp:** Phương pháp này áp dụng Design Pattern một cách trực tiếp, không cần thay đổi cấu trúc của code. 106 | 107 | - **Phương pháp gián tiếp:** Phương pháp này sử dụng các thư viện hoặc framework để áp dụng Design Pattern. 108 | 109 | 110 | ## Lợi ích của việc sử dụng Design Pattern trong phát triển phần mềm 111 | 112 | - **Giúp giải quyết vấn đề một cách hiệu quả và tối ưu:** Design Pattern cung cấp các giải pháp đã được kiểm nghiệm và tối ưu hoá, giúp các lập trình viên giải quyết các vấn đề một cách nhanh chóng và hiệu quả hơn. 113 | - **Tăng tính tái sử dụng của code:** Design Pattern giúp các lập trình viên tái sử dụng code đã có, từ đó giảm thiểu thời gian và công sức phát triển phần mềm. 114 | - **Tăng tính linh hoạt và mở rộng của phần mềm:** Design Pattern giúp phần mềm linh hoạt và dễ dàng mở rộng khi có nhu cầu thay đổi. 115 | - **Tăng tính bảo trì và bảo dưỡng của phần mềm:** Design Pattern giúp phền mềm dễ dàng bảo trì và bảo dưỡng hơn. 116 | - **Tăng tính dễ hiểu và dễ đọc của code:** Design Pattern giúp code dễ hiểu và dễ đọc hơn, giúp việc công tá giữa các lập trình viên trở nên dễ dàng. 117 | 118 | ## Lưu ý khi áp dụng Design Pattern 119 | 120 | Khi áp dụng Design Pattern, các lập trình viên cần lưu ý những điểm sau: 121 | 122 | - **Không nên áp dụng Design Pattern một cách cứng nhắc:** Design Pattern là một giải pháp tổng thể, không phải là một giải pháp hoàn hảo. Các lập trình viên cần linh hoạt trong việc áp dụng Design Pattern để phù hợp với nhu cầu cụ thể của dự án. 123 | - **Không nên làm dụng Design Pattern:** Design pattern không phải là một giải pháp cho mọi vấn đề. Các lập trình viên chỉ nên áp dụng Design Pattern khi nó thực sự cần thiết. 124 | - **Cần có thời gian để học hỏi và nghiên cứu Design Pattern:** Design Pattern là một kỹ thuật phức tạp, cần có thời gian để học hỏi và nghiên cứu. Các lập trình viên không nên vội vàng áp dụng Design Pattern mà không hiểu rõ bản chất và cách hoạt động của nó. 125 | -------------------------------------------------------------------------------- /Writerside/topics/Prototype.md: -------------------------------------------------------------------------------- 1 | # Prototype 2 | 3 | ## Giới thiệu 4 | 5 | Trong chương trước, chúng ta đã tìm hiểu về các Creational Design Pattern, bao gồm Abstract Factory, Builder, Factory Method giúp khởi tạo đối tượng một cách linh hoạt. Tiếp theo, chúng ta sẽ đi tìm hiểu Prototype - một Pattern thuộc nhóm này với mục đích tạo ra bản sao của các đối tượng đã tồn tại. 6 | 7 | Prototype là một Creational Design Pattern cho phép sao chép các đối tượng hiện có thay vì khởi tạo chúng từ đầu. 8 | 9 | Cụ thể, Prototype Pattern định nghĩa một kiểu đối tượng (Prototype) có khả năng tự nhân bản bằng cách clone chính bản thân nó, tạo ra một bản sao độc lập với đối tượng gốc. 10 | 11 | Mục đích của Pattern này là tạo ra các đối tượng mới bằng cách clone từ đối tượng hiện có thay vì khởi tạo, tiết kiệm chi phí tạo mới đối tượng, đặc biệt là các đối tượng phức tạp. Ngoài ra, nó che giấu logic khởi tạo và cung cấp khả năng tạo các đối tượng tương tự một cách hiệu quả. 12 | 13 | Bằng cách sử dụng Prototype Pattern, chúng ta có thể tạo ra các đối tượng mới một cách nhanh chóng và hiệu quả hơn. Chúng ta sẽ cùng tìm hiểu kỹ hơn về Pattern này trong các phần sau. 14 | 15 | ## Đặt vấn đề 16 | 17 | Trong nhiều ứng dụng, việc khởi tạo các đối tượng là một quá trình tốn kém, phức tạp. Chẳng hạn trong một game, việc tạo mới đối tượng Nhân Vật cần phải load dữ liệu, giải mã, khởi tạo trang phục và vũ khí... 18 | 19 | Tuy nhiên, thường có nhiều nhân vật chỉ khác biệt ở một vài thuộc tính nhỏ. Ví dụ Mario và Luigi có ngoại hình và kỹ năng gần giống nhau, chỉ khác tên và màu áo. 20 | 21 | Nếu phải khởi tạo hoàn toàn từ đầu các nhân vật này thì rất tốn kém và lãng phí tài nguyên. 22 | 23 | Chúng ta cần một cách để tạo ra các đối tượng tương tự một cách hiệu quả hơn, bằng cách tận dụng lại những đối tượng đã khởi tạo từ trước. Prototype Pattern ra đời nhằm giải quyết bài toán này. 24 | 25 | ## Giải quyết 26 | 27 | Prototype Pattern giải quyết bài toán bằng cách: 28 | 29 | ```mermaid 30 | classDiagram 31 | 32 | Prototype <|-- Character 33 | Client --> Prototype 34 | 35 | class Prototype { 36 | <> 37 | +clone() 38 | } 39 | 40 | class Character { 41 | -name 42 | -outfit 43 | -weapon 44 | +clone() 45 | } 46 | 47 | class Client { 48 | +createNewCharacter() 49 | } 50 | 51 | Client --> Character 52 | ``` 53 | 54 | - Định nghĩa một interface Prototype chung cho các đối tượng nhân vật có thể clone. 55 | 56 | - Các lớp nhân vật cụ thể (Concrete Prototype) sẽ triển khai interface này và cung cấp hiện thực cho phương thức clone(). Phương thức clone() sẽ sao chép giá trị các trường dữ liệu của đối tượng sang một đối tượng mới. 57 | 58 | - Tạo một đối tượng nhân vật ban đầu với quá trình khởi tạo đầy đủ. 59 | 60 | - Khi cần tạo nhân vật mới tương tự, client sẽ gọi phương thức clone() trên đối tượng ban đầu để tạo ra bản sao. Sau đó có thể thay đổi các thuộc tính cần thiết trên đối tượng mới. 61 | 62 | Như vậy, Prototype Pattern cho phép tạo ra các đối tượng nhân vật mới một cách nhanh chóng và hiệu quả hơn so với khởi tạo lại từ đầu. 63 | 64 | ## Cấu trúc 65 | 66 | Để hiểu rõ cách tổ chức và hoạt động của Prototype Pattern, chúng ta cùng phân tích kỹ hơn cấu trúc của Pattern này. 67 | 68 | ```mermaid 69 | classDiagram 70 | 71 | Prototype <|-- ConcretePrototype1 72 | Prototype <|-- ConcretePrototype2 73 | Client --> Prototype 74 | 75 | class Prototype { 76 | <> 77 | + clone() 78 | } 79 | 80 | class ConcretePrototype1 { 81 | - field1 82 | - field2 83 | + clone() 84 | } 85 | 86 | class ConcretePrototype2 { 87 | - field3 88 | - field4 89 | + clone() 90 | } 91 | 92 | class Client { 93 | + operation() 94 | } 95 | 96 | Client --> ConcretePrototype1 97 | ConcretePrototype1 ..> ConcretePrototype1 : clone() 98 | Client --> ConcretePrototype2 99 | ConcretePrototype2 ..> ConcretePrototype2 : clone() 100 | ``` 101 | 102 | Các thành phần chính trong Prototype Pattern bao gồm: 103 | 104 | - Prototype: định nghĩa một interface chung, khai báo phương thức clone() cho việc sao chép. Đây là giao diện mà Client sẽ tương tác để tạo ra các đối tượng. 105 | - ConcretePrototype: các lớp cụ thể triển khai interface Prototype. Chúng cung cấp hiện thực cho phương thức clone() để sao chép chính bản thân mình, tạo ra một bản sao độc lập. 106 | - Client: tương tác với các đối tượng thông qua interface Prototype, không phụ thuộc vào các lớp cụ thể. Client khởi tạo một ConcretePrototype ban đầu với đầy đủ các bước. Sau đó, nó sẽ sử dụng đối tượng này như một Prototype để nhân bản thành các đối tượng mới thay vì phải khởi tạo lại từ đầu. 107 | 108 | ## Cách triển khai 109 | 110 | Mẫu thiết kế Prototype cho phép bạn tạo ra các đối tượng mới bằng cách sao chép (clone) các đối tượng đã tồn tại, thay vì tạo mới chúng từ đầu. Dưới đây là một ví dụ với một giao diện `CloneableShape` 111 | 112 | ```java 113 | public interface CloneableShape extends Cloneable { 114 | CloneableShape clone(); 115 | void draw(); 116 | } 117 | ``` 118 | 119 | Sau đó, bạn tạo các lớp cụ thể kế thừa từ `CloneableShape` và triển khai phương thức `clone()` và `draw()`. Ví dụ, một lớp `Circle`: 120 | 121 | ```java 122 | public class Circle implements CloneableShape { 123 | private int radius; 124 | 125 | public Circle(int radius) { 126 | this.radius = radius; 127 | } 128 | 129 | @Override 130 | public CloneableShape clone() { 131 | return new Circle(this.radius); 132 | } 133 | 134 | @Override 135 | public void draw() { 136 | System.out.println("Drawing a circle with radius " + radius); 137 | } 138 | } 139 | ``` 140 | 141 | Tạo một lớp sử dụng Prototype Pattern để tạo và quản lý các đối tượng. Ví dụ, lớp ShapeCache: 142 | 143 | ```java 144 | import java.util.HashMap; 145 | import java.util.Map; 146 | 147 | public class ShapeCache { 148 | private static Map shapeMap = new HashMap<>(); 149 | 150 | public static CloneableShape getShape(String shapeId) { 151 | CloneableShape cachedShape = shapeMap.get(shapeId); 152 | return (cachedShape != null) ? cachedShape.clone() : null; 153 | } 154 | 155 | public static void loadCache() { 156 | Circle circle = new Circle(10); 157 | shapeMap.put("1", circle); 158 | 159 | Square square = new Square(5); 160 | shapeMap.put("2", square); 161 | 162 | // Add more shapes as needed 163 | } 164 | } 165 | ``` 166 | 167 | Cuối cùng, bạn có thể sử dụng ShapeCache để sao chép các đối tượng mà bạn cần: 168 | 169 | ```java 170 | public class Main { 171 | public static void main(String[] args) { 172 | ShapeCache.loadCache(); 173 | 174 | CloneableShape clonedCircle = ShapeCache.getShape("1"); 175 | clonedCircle.draw(); 176 | 177 | CloneableShape clonedSquare = ShapeCache.getShape("2"); 178 | clonedSquare.draw(); 179 | } 180 | } 181 | ``` 182 | 183 | Trong ví dụ này, chúng ta đã tạo một số hình dạng và lưu chúng trong ShapeCache. Sau đó, chúng ta có thể sao chép (clone) các hình dạng mà không cần tạo mới chúng từ đầu. 184 | 185 | ## Ví dụ 186 | 187 | Giả sử bạn đang phát triển một ứng dụng quản lý thông tin cá nhân. Trong ứng dụng này, mỗi người có một hồ sơ cá nhân với thông tin cơ bản bao gồm tên, ngày sinh và địa chỉ. 188 | 189 | 190 | Để triển khai Mẫu thiết kế Prototype, bạn bắt đầu bằng việc tạo một giao diện `Profile` định nghĩa phương thức clone: 191 | 192 | 193 | ```java 194 | public interface Profile { 195 | Profile cloneProfile(); 196 | void printProfile(); 197 | } 198 | ``` 199 | 200 | Tiếp theo, bạn tạo một lớp cụ thể `VietnameseProfile` kế thừa từ giao diện `Profile` và triển khai các phương thức `cloneProfile` và `printProfile`: 201 | 202 | ```java 203 | public class VietnameseProfile implements Profile { 204 | private String name; 205 | private String dateOfBirth; 206 | private String address; 207 | 208 | public VietnameseProfile(String name, String dateOfBirth, String address) { 209 | this.name = name; 210 | this.dateOfBirth = dateOfBirth; 211 | this.address = address; 212 | } 213 | 214 | @Override 215 | public Profile cloneProfile() { 216 | return new VietnameseProfile(name, dateOfBirth, address); 217 | } 218 | 219 | @Override 220 | public void printProfile() { 221 | System.out.println("Họ tên: " + name); 222 | System.out.println("Ngày sinh: " + dateOfBirth); 223 | System.out.println("Địa chỉ: " + address); 224 | } 225 | } 226 | ``` 227 | 228 | Sau đó, bạn có thể sử dụng Mẫu thiết kế Prototype để sao chép các hồ sơ cá nhân mà không cần tạo mới chúng từ đầu: 229 | 230 | ```java 231 | public class Main { 232 | public static void main(String[] args) { 233 | // Tạo một hồ sơ cá nhân gốc 234 | Profile originalProfile = new VietnameseProfile("Nguyễn Văn A", "01/01/1990", "Hà Nội"); 235 | 236 | // Sao chép hồ sơ cá nhân 237 | Profile clonedProfile = originalProfile.cloneProfile(); 238 | 239 | // In thông tin hồ sơ cá nhân gốc và sao chép 240 | System.out.println("Thông tin hồ sơ cá nhân gốc:"); 241 | originalProfile.printProfile(); 242 | 243 | System.out.println("\nThông tin hồ sơ cá nhân sao chép:"); 244 | clonedProfile.printProfile(); 245 | } 246 | } 247 | ``` 248 | 249 | Kết quả, bạn có thể thấy rằng thông tin hồ sơ cá nhân đã được sao chép thành công mà không ảnh hưởng đến hồ sơ gốc. Điều này cho phép bạn tạo nhiều bản sao của hồ sơ cá nhân một cách dễ dàng và tiết kiệm thời gian. 250 | 251 | ## So sánh với các Pattern khác 252 | 253 | - **Factory Method/Abstract Factory vs. Prototype**: Factory Method và Abstract Factory tạo ra đối tượng mới mỗi khi được gọi, trong khi Prototype sử dụng sao chép từ đối tượng đã tồn tại. Factory Method tập trung vào việc tạo các đối tượng dựa trên một giao diện chung, trong khi Prototype giúp tạo bản sao của đối tượng cụ thể. Prototype thường sử dụng trong các tình huống mà bạn muốn sao chép một đối tượng hiện có mà không cần biết cụ thể loại đối tượng đó. 254 | 255 | - **Builder vs. Prototype**: Builder tách biệt quá trình khởi tạo phức tạp ra khỏi đối tượng, cho phép bạn xây dựng một đối tượng từ các phần khác nhau một cách linh hoạt. Prototype, ngược lại, che giấu logic khởi tạo bằng cách sao chép đối tượng đã có sẵn. Builder thường được sử dụng khi bạn muốn xây dựng một đối tượng bước cuối cùng theo từng phần, trong khi Prototype giúp bạn tạo nhanh các bản sao của đối tượng hiện có. 256 | 257 | ## Kết luận 258 | 259 | Mẫu thiết kế Prototype rất hữu ích khi quá trình khởi tạo đối tượng phức tạp và bạn cần tạo nhiều đối tượng tương tự. Nó giúp bạn tiết kiệm thời gian và nguồn lực bằng cách sao chép đối tượng hiện có thay vì tạo mới từ đầu. Tuy nhiên, bạn cần cân nhắc chi phí của việc sao chép so với việc tạo mới khi áp dụng mẫu này, vì việc sao chép có thể tốn nhiều tài nguyên hơn trong một số trường hợp. -------------------------------------------------------------------------------- /Writerside/topics/Singleton.md: -------------------------------------------------------------------------------- 1 | # Singleton 2 | 3 | ## Giới thiệu 4 | 5 | Singleton là một Design Pattern thuộc nhóm Creational Pattern. Nó đảm bảo chỉ duy nhất một thể hiện của một lớp được tạo ra trong suốt chương trình. 6 | ### Đặt vấn đề 7 | 8 | Trong nhiều trường hợp, cần đảm bảo chỉ có một thể hiện của một lớp. Ví dụ trong hệ thống quản lý người dùng, chỉ nên có duy nhất một đối tượng UserManager để quản lý người dùng. 9 | 10 | Nếu tạo nhiều đối tượng UserManager có thể dẫn đến: 11 | 12 | - Dữ liệu bị trùng lặp 13 | - Xung đột tài nguyên 14 | - Khó kiểm soát 15 | 16 | ```mermaid 17 | graph TD 18 | A[User Management System] --> B1[UserManager 1] 19 | A --> B2[UserManager 2] 20 | A --> B3[UserManager 3] 21 | 22 | B1 --> C[User 1] 23 | B2 --> D[User 2] 24 | B3 --> E[User 3] 25 | 26 | classDef grey fill:#dddddd,stroke:#333333,stroke-width:2px; 27 | classDef pink fill:#ffd6d6,stroke:#333,stroke-width:2px; 28 | 29 | class A grey 30 | class B1,B2,B3 grey 31 | class C,D,E pink 32 | ``` 33 | 34 | ### Giải quyết 35 | 36 | Singleton giải quyết bằng cách đảm bảo chỉ tạo duy nhất một thể hiện trong toàn bộ chương trình. 37 | 38 | ```mermaid 39 | graph TD 40 | 41 | A[User Management System] --> B[UserManager] 42 | 43 | B --> C[User 1] 44 | B --> D[User 2] 45 | B --> E[User 3] 46 | 47 | classDef grey fill:#dddddd,stroke:#333333,stroke-width:2px; 48 | classDef pink fill:#ffd6d6,stroke:#333,stroke-width:2px; 49 | 50 | class A grey 51 | class B grey 52 | class C,D,E pink 53 | ``` 54 | 55 | Giải thích: 56 | 57 | - Lớp UserManager được triển khai Singleton 58 | - Chỉ có DUY NHẤT một đối tượng UserManager trong hệ thống 59 | - Quản lý tất cả người dùng một cách tập trung 60 | - Tránh được các vấn đề như dữ liệu trùng lặp, xung đột tài nguyên, khó kiểm soát 61 | 62 | Với cách triển khai này, chỉ có một đối tượng UserManager duy nhất được tạo ra, và đối tượng này có thể được truy cập từ bất kỳ nơi nào trong chương trình. 63 | 64 | ### Cấu tạo 65 | 66 | Singleton Pattern có cấu trúc đơn giản, bao gồm các thành phần sau: 67 | 68 | ```mermaid 69 | classDiagram 70 | direction TB 71 | class Singleton { 72 | -static instance:Singleton 73 | -Singleton() 74 | +static getInstance() : Singleton 75 | } 76 | 77 | class Client { 78 | +main() 79 | } 80 | 81 | Client --> Singleton 82 | Singleton ..> Singleton : return instance 83 | ``` 84 | 85 | - Lớp Singleton: Lớp này chứa các phương thức và biến cần thiết để triển khai Singleton Pattern. 86 | - Phương thức khởi tạo private: Phương thức này chỉ có thể được gọi từ bên trong lớp. 87 | - Biến static private: Biến này giữ đối tượng của lớp. 88 | - Phương thức static public để trả về đối tượng của lớp: Phương thức này trả về đối tượng của lớp. 89 | 90 | 91 | ## Cách triển khai 92 | 93 | Có nhiều cách để triển khai Singleton Pattern trong Java. Một cách phổ biến là sử dụng một biến static private để lưu trữ instance của class. 94 | 95 | ```java 96 | public class Singleton { 97 | 98 | private static Singleton instance; 99 | 100 | private Singleton() { 101 | // Constructor is private to prevent direct instantiation 102 | } 103 | 104 | public static Singleton getInstance() { 105 | if (instance == null) { 106 | instance = new Singleton(); 107 | } 108 | return instance; 109 | } 110 | } 111 | ``` 112 | 113 | Cách triển khai này đảm bảo rằng chỉ có một instance của Singleton được tạo ra. Khi một đối tượng Singleton được yêu cầu, phương thức `getInstance()` sẽ kiểm tra xem instance đã tồn tại hay chưa. Nếu chưa, phương thức sẽ tạo ra một instance mới. Nếu đã tồn tại, phương thức sẽ trả về instance hiện tại. 114 | 115 | Một cách triển khai khác của Singleton Pattern là sử dụng một biến static final private. 116 | 117 | ```java 118 | public final class Singleton { 119 | 120 | private static final Singleton instance = new Singleton(); 121 | 122 | private Singleton() { 123 | // Constructor is private to prevent direct instantiation 124 | } 125 | 126 | public static Singleton getInstance() { 127 | return instance; 128 | } 129 | } 130 | ``` 131 | 132 | Cách triển khai này tương tự như cách triển khai đầu tiên, nhưng nó sử dụng một biến static final private thay vì một biến static private. Cách triển khai này có một số ưu điểm như sau: 133 | 134 | - Sử dụng biến static final private sẽ ngăn chặn việc thay đổi giá trị của biến instance. 135 | - Cấu trúc code sẽ gọn gàng hơn. 136 | 137 | 138 | ## Ví dụ minh họa 139 | 140 | Dưới đây là một ví dụ minh họa cách sử dụng Singleton Pattern để tạo một đối tượng DatabaseConnection. 141 | 142 | ```java 143 | public class DatabaseConnection { 144 | 145 | private static final DatabaseConnection instance = new DatabaseConnection(); 146 | 147 | private DatabaseConnection() { 148 | // Connect to database 149 | } 150 | 151 | public static DatabaseConnection getInstance() { 152 | return instance; 153 | } 154 | 155 | public void query(String sql) { 156 | // Execute query 157 | } 158 | } 159 | ``` 160 | 161 | Trong ví dụ này, DatabaseConnection là một class singleton. Nó có một phương thức getInstance() để truy cập instance duy nhất của class. 162 | 163 | ## So sánh 164 | 165 | Singleton Pattern có thể được so sánh với một số Design Pattern tương tự, chẳng hạn như: 166 | 167 | - Factory Pattern: Factory Pattern cung cấp một cách để tạo các đối tượng của lớp một cách linh hoạt. Tuy nhiên, Factory Pattern không đảm bảo rằng chỉ có một đối tượng của lớp được tạo ra. 168 | - Prototype Pattern: Prototype Pattern cung cấp một cách để tạo các bản sao của đối tượng. Prototype Pattern cũng có thể được sử dụng để tạo một đối tượng duy nhất của lớp. Tuy nhiên, Prototype Pattern có thể phức tạp hơn Singleton Pattern. 169 | 170 | ## Lưu ý 171 | 172 | Khi áp dụng Singleton Pattern, cần lưu ý một số điểm sau: 173 | 174 | - Singleton Pattern có thể làm giảm tính linh hoạt của ứng dụng. Ví dụ, nếu bạn cần tạo ra nhiều instance của một class, bạn sẽ cần phải thay đổi code để xóa phương thức getInstance(). 175 | - Singleton Pattern có thể gây ra vấn đề khi test. Ví dụ, nếu bạn đang test một class sử dụng Singleton Pattern, bạn sẽ cần tạo ra một instance giả của class đó. 176 | 177 | 178 | ## Kết luận 179 | 180 | Singleton Pattern là một Design Pattern hữu ích trong những trường hợp cần đảm bảo rằng chỉ có một thể hiện duy nhất của một lớp được tạo ra. Tuy nhiên, cần lưu ý những điểm hạn chế của Singleton Pattern khi áp dụng. 181 | 182 | Dưới đây là một số hướng dẫn sử dụng Singleton Pattern: 183 | 184 | - Nên sử dụng Singleton Pattern khi cần đảm bảo rằng chỉ có một thể hiện duy nhất của một lớp được tạo ra. 185 | - Tránh sử dụng Singleton Pattern khi không cần thiết. 186 | - Hạn chế sử dụng Singleton trong các hệ thống lớn hoặc phức tạp. 187 | 188 | 189 | -------------------------------------------------------------------------------- /Writerside/topics/Structural-Patterns.md: -------------------------------------------------------------------------------- 1 | # Structural Patterns 2 | 3 | Structural Patterns liên quan đến cấu trúc và mối quan hệ giữa các lớp và đối tượng nhằm tạo ra cấu trúc phần mềm dễ thay đổi và bảo trì hơn. 4 | 5 | Các Pattern thuộc nhóm này gồm: 6 | 7 | ## [Adapter](Adapter.md) 8 | 9 | Cho phép giao tiếp giữa các interface không tương thích 10 | 11 | ## [Bridge](Bridge.md) 12 | 13 | Tách rời một lớp phức tạp thành hai phần riêng biệt: trừu tượng và triển khai. 14 | 15 | ## [Composite](Composite.md) 16 | 17 | Tạo ra cấu trúc cây để biểu diễn mối quan hệ whole-part giữa các đối tượng. 18 | 19 | ## [Decorator](Decorator.md) 20 | 21 | Dynamically thêm chức năng mới cho đối tượng mà không ảnh hưởng đến các đối tượng khác. 22 | 23 | ## [Facade](Facade.md) 24 | 25 | Cung cấp một giao diện đơn giản cho một nhóm các lớp phức tạp. 26 | 27 | ## [Flyweight](Flyweight.md) 28 | 29 | Sử dụng chia sẻ để hỗ trợ tao hàng loạt các đối tượng hiệu quả hơn. 30 | 31 | ## [Proxy](Proxy.md) 32 | 33 | Đại diện cho một đối tượng khác để kiểm soát truy cập vào đối tượng đó. 34 | 35 | Các Pattern này giải quyết vấn đề cấu trúc và mối quan hệ giữa các thành phần trong phần mềm để tối ưu hóa tính linh hoạt, bảo trì và tái sử dụng. -------------------------------------------------------------------------------- /Writerside/v.list: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Writerside/writerside.cfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/.DS_Store -------------------------------------------------------------------------------- /docs/Book/1. Intro.md: -------------------------------------------------------------------------------- 1 | # 1. Giới thiệu Design Pattern 2 | 3 | > [!WARNING] 4 | > * Bài này sẽ được cập nhât ở [github sau](https://github.com/nguyenphuc22/Design-Patterns/blob/main/Writerside/topics/Intro.md) và [website sau](https://nguyenphuc22.github.io/Design-Patterns/intro.html). 5 | > * File này sẽ được xoá vào cập nhật version_1 6 | 7 | 8 | ## Định nghĩa Design Pattern 9 | 10 | Design Pattern là một mô hình thiết kế được sử dụng để giải quyết một vấn đề cụ thể trong lập trình. Nó cung cấp một giải pháp đã được kiểm nghiệm và tối ưu hóa, giúp các lập trình viên tiết kiệm thời gian và công sức khi phát triển phần mềm 11 | 12 | ## Lịch sử ra đời và phát triển 13 | 14 | Design Pattern được khai sinh vào những năm 1970 với sự phát triển của lập trình hướng đối tượng (OOP). Kể từ đó, nó đã trở thành một phần quan trọng trong quá trình phát triển phần mềm. 15 | 16 | Năm 1994, ba lập trình viên Erich Gamma, Richard Helm, Ralph Johnson và John Vlissides đã xuất bản cuốn sách "Design Patterns: Elements Of Resuable Object - Oriented Software". Cuốn sách này đã trở thành một trong những tài liệu tham khảo quan trọng nhất về Design Pattern. 17 | 18 | Trong những năm gần đây, Design Pattern tiếp tục được phát triển và mở rộng. Ngày càng có nhiều Design Pattern mới được giới thiệu, phù hợp với các yêu cầu mới của lâp trình. 19 | 20 | ## Ý nghĩa và lợi ích của Design Pattern 21 | 22 | Design Pattern mang lại nhiều ý nghĩa và lợi ích cho lập trình, bao gồm: 23 | 24 | - **Giúp giải quyết vấn đề một cách hiệu quả và tối ưu:** Design Pattern cung cấp các giải pháp đã được kiểm nghiệm và tối ưu hóa, giúp các lập trình viên giải quyết các vấn đề một cách nhanh chóng và hiêu quả. 25 | - **Tăng tính tái sử dụng của code:** Design Pattern giúp các lập trình viên tái sử dụng code đã có, từ đó giảm thiểu thời gian và công ức phát triển phần mềm. 26 | - **Tăng tính bảo trì và bảo dưỡng của phần mềm:** Design Pattern giúp phần mềm dễ dàng bảo trì và bảo dưỡng hơn. 27 | - **Tăng tính dể hiểu và dễ đọc của code:** Design Pattern giúp code dễ hiểu và dễ đọc hơn, giúp việc công tác giữa các lập trình viên trở nên dễ dàng hơn. 28 | 29 | Design Pattern là một kỹ thuật nâng cao của OOP, nó cực kì quan trọng trong lập trình. Nó mang lại nhiều ý nghĩa và lợi ích cho lập trình, giúp các lập trình viên phát triển phần mềm hiệu quả hơn. 30 | 31 | # 2. Phân loại Design Pattern 32 | 33 | ## Creational Design Patterns 34 | 35 | Creational Design Patterns liên quan tới việc khởi tạo đối tượng. Nhóm pattern này cung cấp các cơ chế tạo đối tượng một cách linh hoạt và phù hợp với bối cảnh sử dụng. Một số pattern phổ biến: 36 | 37 | - [Singleton](2.1%20Singleton.md), [Factory Method](2.3%20Factory%20Method.md), [Abstract Factory](2.4%20Abstract%20Factory.md), [Builder](2.2%20Builder.md), [Prototype](2.5%20Prototype.md) 38 | 39 | Sử dụng Creational Patterns giúp tạo ra các đối tượng một cách linh hoạt, dễ dàng thay đổi và tối ưu hóa bộ nhớ. 40 | ## Structural Design Patterns 41 | 42 | Structural Patterns liên quan tới cấu trúc và mối quan hệ giữa các lớp, đối tượng. Nhóm này giúp xây dựng cấu trúc phần mềm dễ thay đổi và bảo trì. Một số pattern: 43 | 44 | - [Adapter](3.1%20Adapter.md), [Bridge](3.2%20Bridge.md), [Composite](3.4%20Composite.md), [Decorator](3.5%20Decorator.md), [Facade](3.6%20Facade.md), [Flyweight](3.7%20Flyweight.md), [Proxy](3.8%20Proxy.md) 45 | 46 | Sử dụng Structural Patterns giúp xây dựng hệ thống linh hoạt, dễ mở rộng và tối ưu hóa bộ nhớ. 47 | 48 | ## Behavioral Design Patterns 49 | 50 | Behavioral Patterns liên quan tới hành vi giao tiếp giữa các đối tượng. Nhóm này giúp định nghĩa rõ ràng mối quan hệ giữa các object. Một số pattern: 51 | 52 | - [Chain of Responsibility](4.1%20Chain%20of%20Responsibility.md), [Command](4.2%20Command.md), [Iterator](4.3%20Iterator.md), [Mediator](4.4%20Mediator.md), [Memento](4.5%20Memento.md), [Observer](4.6%20Observer.md), [State](4.7%20State.md), [Strategy](4.8%20Strategy.md), [Template Method](4.9%20Template%20Method.md), [Visitor](4.10%20Visitor.md) 53 | 54 | Sử dụng Behavioral Patterns giúp tạo hệ thống linh hoạt, dễ thay đổi và tối ưu hóa hiệu suất. 55 | 56 | # 3. Sử dụng Design Pattern 57 | 58 | ## Nguyên tắc và phương pháp áp dụng Design Pattern 59 | 60 | ### Nguyên Tắc 61 | 62 | Để áp dụng Design Pattern hiệu quả, các lập trinh viên cần nắm được các nguyên tắc và phương pháp sau đây: 63 | 64 | - **Nguyên tắc đầu tiên là phải hiểu rõ vấn đề cần giải quyết:** Trước khi áp dụng Design Pattern, các lập trinh viên cần hiểu rõ vấn đề cần giải quyết là gì. Từ đó, họ có thể lựa chọn được Design Pattern phù hợp nhất. 65 | 66 | - **Nguyên tắc thứ hai là phải hiểu rõ Design Pattern:** Các lập trình viên cần hiểu rõ bản chất và cách hoạt động của Design Pattern. Từ đó, họ có thể áp dụng Design Pattern một cách chính xác và hiệu quả. 67 | 68 | - **Nguyên tắc thứ ba là phải linh hoạt trong việc áp dụng Design Pattern:** Không phải lúc nào cũng có thể áp dụng Design Pattern một cách cứng nhắc. Các lập trình viên cần linh hoạt trong việc áp dụng Design Pattern để phù hợp với nhu cầu cụ thể của dự án. 69 | 70 | ### Phương pháp 71 | 72 | - **Phương pháp trực tiếp:** Phương pháp này áp dụng Design Pattern một cách trực tiếp, không cần thay đổi cấu trúc của code. 73 | 74 | - **Phương pháp gián tiếp:** Phương pháp này sử dụng các thư viện hoặc framework để áp dụng Design Pattern. 75 | 76 | 77 | ## Lợi ích của việc sử dụng Design Pattern trong phát triển phần mềm 78 | 79 | - **Giúp giải quyết vấn đề một cách hiệu quả và tối ưu:** Design Pattern cung cấp các giải pháp đã được kiểm nghiệm và tối ưu hoá, giúp các lập trình viên giải quyết các vấn đề một cách nhanh chóng và hiệu quả hơn. 80 | - **Tăng tính tái sử dụng của code:** Design Pattern giúp các lập trình viên tái sử dụng code đã có, từ đó giảm thiểu thời gian và công sức phát triển phần mềm. 81 | - **Tăng tính linh hoạt và mở rộng của phần mềm:** Design Pattern giúp phần mềm linh hoạt và dễ dàng mở rộng khi có nhu cầu thay đổi. 82 | - **Tăng tính bảo trì và bảo dưỡng của phần mềm:** Design Pattern giúp phền mềm dễ dàng bảo trì và bảo dưỡng hơn. 83 | - **Tăng tính dễ hiểu và dễ đọc của code:** Design Pattern giúp code dễ hiểu và dễ đọc hơn, giúp việc công tá giữa các lập trình viên trở nên dễ dàng. 84 | 85 | ## Lưu ý khi áp dụng Design Pattern 86 | 87 | Khi áp dụng Design Pattern, các lập trình viên cần lưu ý những điểm sau: 88 | 89 | - **Không nên áp dụng Design Pattern một cách cứng nhắc:** Design Pattern là một giải pháp tổng thể, không phải là một giải pháp hoàn hảo. Các lập trình viên cần linh hoạt trong việc áp dụng Design Pattern để phù hợp với nhu cầu cụ thể của dự án. 90 | - **Không nên làm dụng Design Pattern:** Design pattern không phải là một giải pháp cho mọi vấn đề. Các lập trình viên chỉ nên áp dụng Design Pattern khi nó thực sự cần thiết. 91 | - **Cần có thời gian để học hỏi và nghiên cứu Design Pattern:** Design Pattern là một kỹ thuật phức tạp, cần có thời gian để học hỏi và nghiên cứu. Các lập trình viên không nên vội vàng áp dụng Design Pattern mà không hiểu rõ bản chất và cách hoạt động của nó. 92 | -------------------------------------------------------------------------------- /docs/Book/2. Creational Patterns.md: -------------------------------------------------------------------------------- 1 | # Giới thiệu Design Pattern 2 | 3 | > [!WARNING] 4 | > * Bài này sẽ được cập nhât ở [github sau](https://github.com/nguyenphuc22/Design-Patterns/blob/main/Writerside/topics/Creational-Patterns.md) và [website sau](https://nguyenphuc22.github.io/Design-Patterns/creational-patterns.html). 5 | > * File này sẽ được xoá vào cập nhật version_1 6 | 7 | 8 | Creational Patterns cung cấp các giải pháp khởi tao đối tượng một cách linh hoạt và phù hợp với bối cảnh sử dụng. Các Pattern thuộc nhóm này gồm: 9 | 10 | ## [Singleton](2.1%20Singleton.md) 11 | 12 | Đảm bảo chỉ có duy nhất một instance của một class trong toàn bộ chương trình. 13 | 14 | ## [Factory Method](2.3%20Factory%20Method.md) 15 | 16 | Định nghĩa một interface để tạo các đối tượng trong superclass nhưng cho phép lớp con quyết định instance nào sẽ được tạo. 17 | 18 | ## [Abstract Factory](2.4%20Abstract%20Factory.md) 19 | 20 | Cung cấp một interface để tạo ra các họ đối tượng liên quan hoặc phụ thuộc lẫn nhau. 21 | 22 | ## [Builder](2.2%20Builder.md) 23 | 24 | Tách biệt quá trình khởi tạo đối tượng phức tạp khởi các đại diện của nó 25 | 26 | ## [Prototype](2.5%20Prototype.md) 27 | 28 | Tạo ra các đối tượng dựa trên một mẫu đối tượng ban đầu 29 | 30 | Các Pattern này giải quyết vấn đề khởi tạo đối tượng một cách linh hoạt, thay vì khởi tạo trực tiếp bằng từ khóa new. Giúp tăng tính mềm dẻo và tái sử dụng code. -------------------------------------------------------------------------------- /docs/Book/2.1 Singleton.md: -------------------------------------------------------------------------------- 1 | # Singleton 2 | 3 | > [!WARNING] 4 | > * Bài này sẽ được cập nhât ở [github sau](https://github.com/nguyenphuc22/Design-Patterns/blob/main/Writerside/topics/Singleton.md) và [website sau](https://nguyenphuc22.github.io/Design-Patterns/singleton.html). 5 | > * File này sẽ được xoá vào cập nhật version_1 6 | 7 | 8 | ## Giới thiệu 9 | 10 | Singleton là một Design Pattern thuộc nhóm Creational Pattern. Nó đảm bảo chỉ duy nhất một thể hiện của một lớp được tạo ra trong suốt chương trình. 11 | ### Đặt vấn đề 12 | 13 | Trong nhiều trường hợp, cần đảm bảo chỉ có một thể hiện của một lớp. Ví dụ trong hệ thống quản lý người dùng, chỉ nên có duy nhất một đối tượng UserManager để quản lý người dùng. 14 | 15 | Nếu tạo nhiều đối tượng UserManager có thể dẫn đến: 16 | 17 | - Dữ liệu bị trùng lặp 18 | - Xung đột tài nguyên 19 | - Khó kiểm soát 20 | 21 | ```mermaid 22 | graph TD 23 | A[User Management System] --> B1[UserManager 1] 24 | A --> B2[UserManager 2] 25 | A --> B3[UserManager 3] 26 | 27 | B1 --> C[User 1] 28 | B2 --> D[User 2] 29 | B3 --> E[User 3] 30 | 31 | classDef grey fill:#dddddd,stroke:#333333,stroke-width:2px; 32 | classDef pink fill:#ffd6d6,stroke:#333,stroke-width:2px; 33 | 34 | class A grey 35 | class B1,B2,B3 grey 36 | class C,D,E pink 37 | ``` 38 | 39 | ### Giải quyết 40 | 41 | Singleton giải quyết bằng cách đảm bảo chỉ tạo duy nhất một thể hiện trong toàn bộ chương trình. 42 | 43 | ```mermaid 44 | graph TD 45 | 46 | A[User Management System] --> B[UserManager] 47 | 48 | B --> C[User 1] 49 | B --> D[User 2] 50 | B --> E[User 3] 51 | 52 | classDef grey fill:#dddddd,stroke:#333333,stroke-width:2px; 53 | classDef pink fill:#ffd6d6,stroke:#333,stroke-width:2px; 54 | 55 | class A grey 56 | class B grey 57 | class C,D,E pink 58 | ``` 59 | 60 | Giải thích: 61 | 62 | - Lớp UserManager được triển khai Singleton 63 | - Chỉ có DUY NHẤT một đối tượng UserManager trong hệ thống 64 | - Quản lý tất cả người dùng một cách tập trung 65 | - Tránh được các vấn đề như dữ liệu trùng lặp, xung đột tài nguyên, khó kiểm soát 66 | 67 | Với cách triển khai này, chỉ có một đối tượng UserManager duy nhất được tạo ra, và đối tượng này có thể được truy cập từ bất kỳ nơi nào trong chương trình. 68 | 69 | ### Cấu tạo 70 | 71 | Singleton Pattern có cấu trúc đơn giản, bao gồm các thành phần sau: 72 | 73 | ```mermaid 74 | classDiagram 75 | direction TB 76 | class Singleton { 77 | -static instance:Singleton 78 | -Singleton() 79 | +static getInstance() : Singleton 80 | } 81 | 82 | class Client { 83 | +main() 84 | } 85 | 86 | Client --> Singleton 87 | Singleton ..> Singleton : return instance 88 | ``` 89 | 90 | - Lớp Singleton: Lớp này chứa các phương thức và biến cần thiết để triển khai Singleton Pattern. 91 | - Phương thức khởi tạo private: Phương thức này chỉ có thể được gọi từ bên trong lớp. 92 | - Biến static private: Biến này giữ đối tượng của lớp. 93 | - Phương thức static public để trả về đối tượng của lớp: Phương thức này trả về đối tượng của lớp. 94 | 95 | 96 | ## Cách triển khai 97 | 98 | Có nhiều cách để triển khai Singleton Pattern trong Java. Một cách phổ biến là sử dụng một biến static private để lưu trữ instance của class. 99 | 100 | ```java 101 | public class Singleton { 102 | 103 | private static Singleton instance; 104 | 105 | private Singleton() { 106 | // Constructor is private to prevent direct instantiation 107 | } 108 | 109 | public static Singleton getInstance() { 110 | if (instance == null) { 111 | instance = new Singleton(); 112 | } 113 | return instance; 114 | } 115 | } 116 | ``` 117 | 118 | Cách triển khai này đảm bảo rằng chỉ có một instance của Singleton được tạo ra. Khi một đối tượng Singleton được yêu cầu, phương thức `getInstance()` sẽ kiểm tra xem instance đã tồn tại hay chưa. Nếu chưa, phương thức sẽ tạo ra một instance mới. Nếu đã tồn tại, phương thức sẽ trả về instance hiện tại. 119 | 120 | Một cách triển khai khác của Singleton Pattern là sử dụng một biến static final private. 121 | 122 | ```java 123 | public final class Singleton { 124 | 125 | private static final Singleton instance = new Singleton(); 126 | 127 | private Singleton() { 128 | // Constructor is private to prevent direct instantiation 129 | } 130 | 131 | public static Singleton getInstance() { 132 | return instance; 133 | } 134 | } 135 | ``` 136 | 137 | Cách triển khai này tương tự như cách triển khai đầu tiên, nhưng nó sử dụng một biến static final private thay vì một biến static private. Cách triển khai này có một số ưu điểm như sau: 138 | 139 | - Sử dụng biến static final private sẽ ngăn chặn việc thay đổi giá trị của biến instance. 140 | - Cấu trúc code sẽ gọn gàng hơn. 141 | 142 | 143 | ## Ví dụ minh họa 144 | 145 | Dưới đây là một ví dụ minh họa cách sử dụng Singleton Pattern để tạo một đối tượng DatabaseConnection. 146 | 147 | ```java 148 | public class DatabaseConnection { 149 | 150 | private static final DatabaseConnection instance = new DatabaseConnection(); 151 | 152 | private DatabaseConnection() { 153 | // Connect to database 154 | } 155 | 156 | public static DatabaseConnection getInstance() { 157 | return instance; 158 | } 159 | 160 | public void query(String sql) { 161 | // Execute query 162 | } 163 | } 164 | ``` 165 | 166 | Trong ví dụ này, DatabaseConnection là một class singleton. Nó có một phương thức getInstance() để truy cập instance duy nhất của class. 167 | 168 | ## So sánh 169 | 170 | Singleton Pattern có thể được so sánh với một số Design Pattern tương tự, chẳng hạn như: 171 | 172 | - Factory Pattern: Factory Pattern cung cấp một cách để tạo các đối tượng của lớp một cách linh hoạt. Tuy nhiên, Factory Pattern không đảm bảo rằng chỉ có một đối tượng của lớp được tạo ra. 173 | - Prototype Pattern: Prototype Pattern cung cấp một cách để tạo các bản sao của đối tượng. Prototype Pattern cũng có thể được sử dụng để tạo một đối tượng duy nhất của lớp. Tuy nhiên, Prototype Pattern có thể phức tạp hơn Singleton Pattern. 174 | 175 | ## Lưu ý 176 | 177 | Khi áp dụng Singleton Pattern, cần lưu ý một số điểm sau: 178 | 179 | - Singleton Pattern có thể làm giảm tính linh hoạt của ứng dụng. Ví dụ, nếu bạn cần tạo ra nhiều instance của một class, bạn sẽ cần phải thay đổi code để xóa phương thức getInstance(). 180 | - Singleton Pattern có thể gây ra vấn đề khi test. Ví dụ, nếu bạn đang test một class sử dụng Singleton Pattern, bạn sẽ cần tạo ra một instance giả của class đó. 181 | 182 | 183 | ## Kết luận 184 | 185 | Singleton Pattern là một Design Pattern hữu ích trong những trường hợp cần đảm bảo rằng chỉ có một thể hiện duy nhất của một lớp được tạo ra. Tuy nhiên, cần lưu ý những điểm hạn chế của Singleton Pattern khi áp dụng. 186 | 187 | Dưới đây là một số hướng dẫn sử dụng Singleton Pattern: 188 | 189 | - Nên sử dụng Singleton Pattern khi cần đảm bảo rằng chỉ có một thể hiện duy nhất của một lớp được tạo ra. 190 | - Tránh sử dụng Singleton Pattern khi không cần thiết. 191 | - Hạn chế sử dụng Singleton trong các hệ thống lớn hoặc phức tạp. 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /docs/Book/2.4 Abstract Factory.md: -------------------------------------------------------------------------------- 1 | # Abstract Factory 2 | 3 | > [!WARNING] 4 | > * Bài này sẽ được cập nhât ở [github sau](https://github.com/nguyenphuc22/Design-Patterns/blob/main/Writerside/topics/Abstract-Factory.md) và [website sau](https://nguyenphuc22.github.io/Design-Patterns/abstract-factory.html). 5 | > * File này sẽ được xoá vào cập nhật version_1 6 | 7 | 8 | ## Giới thiệu 9 | 10 | Trong cuốn sách về Design Pattern, chúng ta đã tìm hiểu về nhóm Creational Pattern, bao gồm những Pattern giúp khởi tạo đối tượng một cách linh hoạt và thuận tiện. Factory Method là một Pattern đã được giới thiệu, giúp tạo ra các đối tượng của một lớp. Tuy nhiên, trong nhiều trường hợp, các đối tượng có quan hệ với nhau và được nhóm thành các họ. Lúc này, chúng ta cần Abstract Factory. 11 | 12 | Abstract Factory cung cấp một interface để tạo ra các họ đối tượng liên quan với nhau một cách linh hoạt. 13 | 14 | ## Đặt vấn đề 15 | 16 | Giả sử bạn đang phát triển một ứng dụng gọi món ăn cho nhà hàng. Các món ăn được phân thành các nhóm: 17 | 18 | - Món lẩu: Thịt bò, rau củ, nấm hương 19 | - Món phở: Bánh phở, thịt bò, giá đỗ 20 | - Món bún: Bún, nem nuong, chả giò 21 | 22 | Khi người dùng gọi món, các nguyên liệu cần được chuẩn bị phù hợp với nhau trong cùng một nhóm món. 23 | 24 | Ngoài ra, nhà hàng thường xuyên thay đổi thực đơn, bổ sung các nhóm món mới. 25 | 26 | Chúng ta cần một cách để dễ dàng tạo ra và thay đổi các nhóm món mà không ảnh hưởng đến code hiện tại. 27 | 28 | ## Giải quyết 29 | 30 | Để giải quyết vấn đề trên, Abstract Factory đưa ra ý tưởng: 31 | 32 | - Tạo interface định nghĩa các phương thức tạo các loại nguyên liệu trừu tượng: thịt, rau, carb, ... 33 | 34 | - Tạo các Concrete Factory triển khai interface này, mỗi Factory tương ứng với một nhóm món, chịu trách nhiệm tạo ra các nguyên liệu phù hợp. 35 | 36 | - Code sẽ sử dụng Abstract Factory để lấy các nguyên liệu một cách tổng quát. 37 | 38 | Như vậy, khi thêm nhóm món mới, chỉ cần tạo thêm Concrete Factory tương ứng, mà không làm ảnh hưởng code hiện tại. 39 | 40 | ## Cấu trúc 41 | 42 | Abstract Factory có cấu trúc gồm các thành phần chính sau: 43 | 44 | ```mermaid 45 | classDiagram 46 | 47 | class AbstractFactory { 48 | <> 49 | +CreateProductA() 50 | +CreateProductB() 51 | } 52 | 53 | AbstractFactory <|-- ConcreteFactory1 54 | AbstractFactory <|-- ConcreteFactory2 55 | 56 | ConcreteProductA1 --|> AbstractProductA 57 | ConcreteProductA2 --|> AbstractProductA 58 | 59 | ConcreteProductB1 --|> AbstractProductB 60 | ConcreteProductB2 --|> AbstractProductB 61 | 62 | 63 | ConcreteFactory1: +CreateProductA() 64 | ConcreteFactory1: +CreateProductB() 65 | 66 | ConcreteFactory2: +CreateProductA() 67 | ConcreteFactory2: +CreateProductB() 68 | 69 | Client --> AbstractFactory 70 | ConcreteFactory1 ..> ConcreteProductA1 71 | ConcreteFactory2 ..> ConcreteProductA2 72 | ConcreteFactory1 ..> ConcreteProductB1 73 | ConcreteFactory2 ..> ConcreteProductB2 74 | 75 | ``` 76 | 77 | - Abstract Factory interface: định nghĩa các phương thức nhà máy trừu tượng để tạo ra các sản phẩm trừu tượng. 78 | - Concrete Factory: cài đặt các phương thức nhà máy cụ thể để tạo ra các sản phẩm cụ thể. Mỗi Concrete Factory tạo ra một tập sản phẩm khác biệt, phù hợp với một variant. 79 | - Abstract Product: định nghĩa interface chung cho một loại sản phẩm trừu tượng. 80 | - Concrete Product: cài đặt các sản phẩm cụ thể, triển khai từ Abstract Product. Mỗi sản phẩm thuộc về một Concrete Factory nhất định. 81 | - Client: sử dụng Abstract Factory và Abstract Product để tương tác với hệ thống. Không cần quan tâm đến các lớp cụ thể. 82 | 83 | ## Cách triển khai 84 | 85 | Đầu tiên, ta định nghĩa interface AbstractFactory: 86 | ```java 87 | interface AbstractFactory { 88 | AbstractProductA createProductA(); 89 | AbstractProductB createProductB(); 90 | } 91 | ``` 92 | Tiếp theo, định nghĩa các Concrete Factory triển khai AbstractFactory: 93 | ```java 94 | class ConcreteFactory1 implements AbstractFactory { 95 | 96 | @Override 97 | AbstractProductA createProductA() { 98 | return new ConcreteProductA1(); 99 | } 100 | 101 | @Override 102 | AbstractProductB createProductB() { 103 | return new ConcreteProductB1(); 104 | } 105 | 106 | } 107 | 108 | class ConcreteFactory2 implements AbstractFactory { 109 | 110 | // implements createProductA() and createProductB() 111 | } 112 | ``` 113 | 114 | Định nghĩa các Abstract Product dưới dạng interface: 115 | 116 | ```java 117 | interface AbstractProductA {} 118 | interface AbstractProductB {} 119 | ``` 120 | 121 | Triển khai các Concrete Product từ Abstract Product: 122 | 123 | ```java 124 | class ConcreteProductA1 implements AbstractProductA {} 125 | 126 | class ConcreteProductB1 implements AbstractProductB {} 127 | ``` 128 | 129 | Cuối cùng, ở Client chúng ta sẽ sử dụng AbstractFactory để tạo ra các Abstract Product mà không cần quan tâm đến các lớp cụ thể: 130 | 131 | ```java 132 | public class Main { 133 | 134 | public static void main(String[] args) { 135 | 136 | // Khởi tạo factory 137 | AbstractFactory factory = new ConcreteFactory1(); 138 | 139 | // Sử dụng factory để lấy các sản phẩm 140 | AbstractProductA productA = factory.createProductA(); 141 | AbstractProductB productB = factory.createProductB(); 142 | 143 | // Sử dụng các sản phẩm 144 | productA.methodA(); 145 | productB.methodB(); 146 | 147 | // Thay đổi factory khác 148 | factory = new ConcreteFactory2(); 149 | 150 | // Lấy lại các sản phẩm 151 | productA = factory.createProductA(); 152 | productB = factory.createProductB(); 153 | 154 | // Sử dụng các sản phẩm mới 155 | } 156 | 157 | } 158 | ``` 159 | ## Ví dụ 160 | 161 | Dưới đây là một ví dụ minh họa về Abstract Factory trong Java: 162 | 163 | 164 | ```java 165 | // Interfaces cho các thành phần món ăn 166 | interface IProtein { 167 | public void prepare(); 168 | } 169 | 170 | interface ICarbohydrate { 171 | public void prepare(); 172 | } 173 | 174 | interface IVegetable { 175 | public void prepare(); 176 | } 177 | 178 | // Các thành phần cụ thể 179 | class Beef implements IProtein { 180 | public void prepare() { 181 | System.out.println("Preparing beef"); 182 | } 183 | } 184 | 185 | class RiceNoodle implements ICarbohydrate { 186 | public void prepare() { 187 | System.out.println("Preparing rice noodle"); 188 | } 189 | } 190 | 191 | // Các thành phần khác... 192 | 193 | // Abstract factory interface 194 | interface FoodFactory { 195 | public IProtein createProtein(); 196 | public ICarbohydrate createCarbohydrate(); 197 | public IVegetable createVegetable(); 198 | } 199 | 200 | // Concrete factory 201 | class LauFactory implements FoodFactory { 202 | 203 | @Override 204 | public IProtein createProtein() { 205 | return new Beef(); 206 | } 207 | 208 | @Override 209 | public ICarbohydrate createCarbohydrate() { 210 | return new RiceNoodle(); 211 | } 212 | 213 | @Override 214 | public IVegetable createVegetable() { 215 | return new Cabbage(); 216 | } 217 | } 218 | 219 | // Client 220 | public class Client { 221 | public static void main(String[] args) { 222 | FoodFactory factory = new LauFactory(); 223 | IProtein protein = factory.createProtein(); 224 | ICarbohydrate carb = factory.createCarbohydrate(); 225 | 226 | protein.prepare(); 227 | carb.prepare(); 228 | } 229 | } 230 | ``` 231 | Chương trình sẽ in ra các bước chuẩn bị cho từng thành phần món lẩu. Bạn có thể dễ dàng thêm các nhóm món khác bằng cách tạo thêm Concrete Factory. 232 | 233 | ## So sánh 234 | 235 | Abstract Factory có thể được so sánh với một số Design Pattern tương tự như: 236 | 237 | - Factory Method: Factory Method chỉ cung cấp phương thức factory để tạo ra đối tượng của một lớp cụ thể. Trong khi đó, Abstract Factory cung cấp interface để tạo ra toàn bộ họ các đối tượng liên quan. 238 | 239 | - Builder Pattern: Builder tập trung vào việc tạo ra một đối tượng phức tạp bằng cách tách quá trình xây dựng ra khỏi biểu diễn. Abstract Factory tập trung vào việc tạo ra các đối tượng thuộc cùng một họ liên quan. 240 | 241 | - Prototype Pattern: Prototype tạo ra đối tượng bằng cách clone đối tượng ban đầu. Abstract Factory tạo ra đối tượng mới mỗi lần được gọi. 242 | 243 | - Singleton Pattern: Singleton chỉ cho phép tồn tại duy nhất một instance. Abstract Factory tạo nhiều đối tượng khác nhau. 244 | 245 | ## Kết luận 246 | 247 | Abstract Factory là một Design Pattern hữu ích, có một số ưu điểm sau: 248 | 249 | - Tách biệt phần triển khai với phần sử dụng code, giảm sự phụ thuộc lẫn nhau giữa các đối tượng. 250 | 251 | - Có thể dễ dàng thay đổi, mở rộng cách tạo đối tượng mà không ảnh hưởng đến phần còn lại của code. 252 | 253 | - Giúp tạo ra các họ đối tượng liên quan một cách thống nhất. 254 | 255 | Tuy nhiên, Pattern cũng có một số nhược điểm cần lưu ý: 256 | 257 | - Cấu trúc phức tạp, nhiều lớp trừu tượng cần phải triển khai. 258 | 259 | - Khó khăn trong việc cân bằng giữa tính linh hoạt và hiệu suất. 260 | 261 | Vì vậy, Abstract Factory phù hợp trong trường hợp cần tạo ra các họ đối tượng liên quan, có tính mở rộng cao. Không nên sử dụng nếu chỉ cần tạo đơn giản một Object. 262 | 263 | Như vậy, với ưu điểm về tính linh hoạt và mở rộng, Abstract Factory là một Pattern rất hữu ích, phổ biến trong thiết kế phần mềm. 264 | -------------------------------------------------------------------------------- /docs/Book/2.5 Prototype.md: -------------------------------------------------------------------------------- 1 | # Prototype Pattern 2 | 3 | > [!WARNING] 4 | > * Bài này sẽ được cập nhât ở [github sau](https://github.com/nguyenphuc22/Design-Patterns/blob/main/Writerside/topics/Prototype.md) và [website sau](https://nguyenphuc22.github.io/Design-Patterns/prototype.html). 5 | > * File này sẽ được xoá vào cập nhật version_1 6 | 7 | 8 | ## Giới thiệu 9 | 10 | Trong chương trước, chúng ta đã tìm hiểu về các Creational Design Pattern, bao gồm Abstract Factory, Builder, Factory Method giúp khởi tạo đối tượng một cách linh hoạt. Tiếp theo, chúng ta sẽ đi tìm hiểu Prototype - một Pattern thuộc nhóm này với mục đích tạo ra bản sao của các đối tượng đã tồn tại. 11 | 12 | Prototype là một Creational Design Pattern cho phép sao chép các đối tượng hiện có thay vì khởi tạo chúng từ đầu. 13 | 14 | Cụ thể, Prototype Pattern định nghĩa một kiểu đối tượng (Prototype) có khả năng tự nhân bản bằng cách clone chính bản thân nó, tạo ra một bản sao độc lập với đối tượng gốc. 15 | 16 | Mục đích của Pattern này là tạo ra các đối tượng mới bằng cách clone từ đối tượng hiện có thay vì khởi tạo, tiết kiệm chi phí tạo mới đối tượng, đặc biệt là các đối tượng phức tạp. Ngoài ra, nó che giấu logic khởi tạo và cung cấp khả năng tạo các đối tượng tương tự một cách hiệu quả. 17 | 18 | Bằng cách sử dụng Prototype Pattern, chúng ta có thể tạo ra các đối tượng mới một cách nhanh chóng và hiệu quả hơn. Chúng ta sẽ cùng tìm hiểu kỹ hơn về Pattern này trong các phần sau. 19 | 20 | ## Đặt vấn đề 21 | 22 | Trong nhiều ứng dụng, việc khởi tạo các đối tượng là một quá trình tốn kém, phức tạp. Chẳng hạn trong một game, việc tạo mới đối tượng Nhân Vật cần phải load dữ liệu, giải mã, khởi tạo trang phục và vũ khí... 23 | 24 | Tuy nhiên, thường có nhiều nhân vật chỉ khác biệt ở một vài thuộc tính nhỏ. Ví dụ Mario và Luigi có ngoại hình và kỹ năng gần giống nhau, chỉ khác tên và màu áo. 25 | 26 | Nếu phải khởi tạo hoàn toàn từ đầu các nhân vật này thì rất tốn kém và lãng phí tài nguyên. 27 | 28 | Chúng ta cần một cách để tạo ra các đối tượng tương tự một cách hiệu quả hơn, bằng cách tận dụng lại những đối tượng đã khởi tạo từ trước. Prototype Pattern ra đời nhằm giải quyết bài toán này. 29 | 30 | ## Giải quyết 31 | 32 | Prototype Pattern giải quyết bài toán bằng cách: 33 | 34 | ```mermaid 35 | classDiagram 36 | 37 | Prototype <|-- Character 38 | Client --> Prototype 39 | 40 | class Prototype { 41 | <> 42 | +clone() 43 | } 44 | 45 | class Character { 46 | -name 47 | -outfit 48 | -weapon 49 | +clone() 50 | } 51 | 52 | class Client { 53 | +createNewCharacter() 54 | } 55 | 56 | Client --> Character 57 | ``` 58 | 59 | - Định nghĩa một interface Prototype chung cho các đối tượng nhân vật có thể clone. 60 | 61 | - Các lớp nhân vật cụ thể (Concrete Prototype) sẽ triển khai interface này và cung cấp hiện thực cho phương thức clone(). Phương thức clone() sẽ sao chép giá trị các trường dữ liệu của đối tượng sang một đối tượng mới. 62 | 63 | - Tạo một đối tượng nhân vật ban đầu với quá trình khởi tạo đầy đủ. 64 | 65 | - Khi cần tạo nhân vật mới tương tự, client sẽ gọi phương thức clone() trên đối tượng ban đầu để tạo ra bản sao. Sau đó có thể thay đổi các thuộc tính cần thiết trên đối tượng mới. 66 | 67 | Như vậy, Prototype Pattern cho phép tạo ra các đối tượng nhân vật mới một cách nhanh chóng và hiệu quả hơn so với khởi tạo lại từ đầu. 68 | 69 | ## Cấu trúc 70 | 71 | Để hiểu rõ cách tổ chức và hoạt động của Prototype Pattern, chúng ta cùng phân tích kỹ hơn cấu trúc của Pattern này. 72 | 73 | ```mermaid 74 | classDiagram 75 | 76 | Prototype <|-- ConcretePrototype1 77 | Prototype <|-- ConcretePrototype2 78 | Client --> Prototype 79 | 80 | class Prototype { 81 | <> 82 | + clone() 83 | } 84 | 85 | class ConcretePrototype1 { 86 | - field1 87 | - field2 88 | + clone() 89 | } 90 | 91 | class ConcretePrototype2 { 92 | - field3 93 | - field4 94 | + clone() 95 | } 96 | 97 | class Client { 98 | + operation() 99 | } 100 | 101 | Client --> ConcretePrototype1 102 | ConcretePrototype1 ..> ConcretePrototype1 : clone() 103 | Client --> ConcretePrototype2 104 | ConcretePrototype2 ..> ConcretePrototype2 : clone() 105 | ``` 106 | 107 | Các thành phần chính trong Prototype Pattern bao gồm: 108 | 109 | - Prototype: định nghĩa một interface chung, khai báo phương thức clone() cho việc sao chép. Đây là giao diện mà Client sẽ tương tác để tạo ra các đối tượng. 110 | - ConcretePrototype: các lớp cụ thể triển khai interface Prototype. Chúng cung cấp hiện thực cho phương thức clone() để sao chép chính bản thân mình, tạo ra một bản sao độc lập. 111 | - Client: tương tác với các đối tượng thông qua interface Prototype, không phụ thuộc vào các lớp cụ thể. Client khởi tạo một ConcretePrototype ban đầu với đầy đủ các bước. Sau đó, nó sẽ sử dụng đối tượng này như một Prototype để nhân bản thành các đối tượng mới thay vì phải khởi tạo lại từ đầu. 112 | 113 | ## Cách triển khai 114 | 115 | Mẫu thiết kế Prototype cho phép bạn tạo ra các đối tượng mới bằng cách sao chép (clone) các đối tượng đã tồn tại, thay vì tạo mới chúng từ đầu. Dưới đây là một ví dụ với một giao diện `CloneableShape` 116 | 117 | ```java 118 | public interface CloneableShape extends Cloneable { 119 | CloneableShape clone(); 120 | void draw(); 121 | } 122 | ``` 123 | 124 | Sau đó, bạn tạo các lớp cụ thể kế thừa từ `CloneableShape` và triển khai phương thức `clone()` và `draw()`. Ví dụ, một lớp `Circle`: 125 | 126 | ```java 127 | public class Circle implements CloneableShape { 128 | private int radius; 129 | 130 | public Circle(int radius) { 131 | this.radius = radius; 132 | } 133 | 134 | @Override 135 | public CloneableShape clone() { 136 | return new Circle(this.radius); 137 | } 138 | 139 | @Override 140 | public void draw() { 141 | System.out.println("Drawing a circle with radius " + radius); 142 | } 143 | } 144 | ``` 145 | 146 | Tạo một lớp sử dụng Prototype Pattern để tạo và quản lý các đối tượng. Ví dụ, lớp ShapeCache: 147 | 148 | ```java 149 | import java.util.HashMap; 150 | import java.util.Map; 151 | 152 | public class ShapeCache { 153 | private static Map shapeMap = new HashMap<>(); 154 | 155 | public static CloneableShape getShape(String shapeId) { 156 | CloneableShape cachedShape = shapeMap.get(shapeId); 157 | return (cachedShape != null) ? cachedShape.clone() : null; 158 | } 159 | 160 | public static void loadCache() { 161 | Circle circle = new Circle(10); 162 | shapeMap.put("1", circle); 163 | 164 | Square square = new Square(5); 165 | shapeMap.put("2", square); 166 | 167 | // Add more shapes as needed 168 | } 169 | } 170 | ``` 171 | 172 | Cuối cùng, bạn có thể sử dụng ShapeCache để sao chép các đối tượng mà bạn cần: 173 | 174 | ```java 175 | public class Main { 176 | public static void main(String[] args) { 177 | ShapeCache.loadCache(); 178 | 179 | CloneableShape clonedCircle = ShapeCache.getShape("1"); 180 | clonedCircle.draw(); 181 | 182 | CloneableShape clonedSquare = ShapeCache.getShape("2"); 183 | clonedSquare.draw(); 184 | } 185 | } 186 | ``` 187 | 188 | Trong ví dụ này, chúng ta đã tạo một số hình dạng và lưu chúng trong ShapeCache. Sau đó, chúng ta có thể sao chép (clone) các hình dạng mà không cần tạo mới chúng từ đầu. 189 | 190 | ## Ví dụ 191 | 192 | Giả sử bạn đang phát triển một ứng dụng quản lý thông tin cá nhân. Trong ứng dụng này, mỗi người có một hồ sơ cá nhân với thông tin cơ bản bao gồm tên, ngày sinh và địa chỉ. 193 | 194 | 195 | Để triển khai Mẫu thiết kế Prototype, bạn bắt đầu bằng việc tạo một giao diện `Profile` định nghĩa phương thức clone: 196 | 197 | 198 | ```java 199 | public interface Profile { 200 | Profile cloneProfile(); 201 | void printProfile(); 202 | } 203 | ``` 204 | 205 | Tiếp theo, bạn tạo một lớp cụ thể `VietnameseProfile` kế thừa từ giao diện `Profile` và triển khai các phương thức `cloneProfile` và `printProfile`: 206 | 207 | ```java 208 | public class VietnameseProfile implements Profile { 209 | private String name; 210 | private String dateOfBirth; 211 | private String address; 212 | 213 | public VietnameseProfile(String name, String dateOfBirth, String address) { 214 | this.name = name; 215 | this.dateOfBirth = dateOfBirth; 216 | this.address = address; 217 | } 218 | 219 | @Override 220 | public Profile cloneProfile() { 221 | return new VietnameseProfile(name, dateOfBirth, address); 222 | } 223 | 224 | @Override 225 | public void printProfile() { 226 | System.out.println("Họ tên: " + name); 227 | System.out.println("Ngày sinh: " + dateOfBirth); 228 | System.out.println("Địa chỉ: " + address); 229 | } 230 | } 231 | ``` 232 | 233 | Sau đó, bạn có thể sử dụng Mẫu thiết kế Prototype để sao chép các hồ sơ cá nhân mà không cần tạo mới chúng từ đầu: 234 | 235 | ```java 236 | public class Main { 237 | public static void main(String[] args) { 238 | // Tạo một hồ sơ cá nhân gốc 239 | Profile originalProfile = new VietnameseProfile("Nguyễn Văn A", "01/01/1990", "Hà Nội"); 240 | 241 | // Sao chép hồ sơ cá nhân 242 | Profile clonedProfile = originalProfile.cloneProfile(); 243 | 244 | // In thông tin hồ sơ cá nhân gốc và sao chép 245 | System.out.println("Thông tin hồ sơ cá nhân gốc:"); 246 | originalProfile.printProfile(); 247 | 248 | System.out.println("\nThông tin hồ sơ cá nhân sao chép:"); 249 | clonedProfile.printProfile(); 250 | } 251 | } 252 | ``` 253 | 254 | Kết quả, bạn có thể thấy rằng thông tin hồ sơ cá nhân đã được sao chép thành công mà không ảnh hưởng đến hồ sơ gốc. Điều này cho phép bạn tạo nhiều bản sao của hồ sơ cá nhân một cách dễ dàng và tiết kiệm thời gian. 255 | 256 | ## So sánh với các Pattern khác 257 | 258 | - **Factory Method/Abstract Factory vs. Prototype**: Factory Method và Abstract Factory tạo ra đối tượng mới mỗi khi được gọi, trong khi Prototype sử dụng sao chép từ đối tượng đã tồn tại. Factory Method tập trung vào việc tạo các đối tượng dựa trên một giao diện chung, trong khi Prototype giúp tạo bản sao của đối tượng cụ thể. Prototype thường sử dụng trong các tình huống mà bạn muốn sao chép một đối tượng hiện có mà không cần biết cụ thể loại đối tượng đó. 259 | 260 | - **Builder vs. Prototype**: Builder tách biệt quá trình khởi tạo phức tạp ra khỏi đối tượng, cho phép bạn xây dựng một đối tượng từ các phần khác nhau một cách linh hoạt. Prototype, ngược lại, che giấu logic khởi tạo bằng cách sao chép đối tượng đã có sẵn. Builder thường được sử dụng khi bạn muốn xây dựng một đối tượng bước cuối cùng theo từng phần, trong khi Prototype giúp bạn tạo nhanh các bản sao của đối tượng hiện có. 261 | 262 | ## Kết luận 263 | 264 | Mẫu thiết kế Prototype rất hữu ích khi quá trình khởi tạo đối tượng phức tạp và bạn cần tạo nhiều đối tượng tương tự. Nó giúp bạn tiết kiệm thời gian và nguồn lực bằng cách sao chép đối tượng hiện có thay vì tạo mới từ đầu. Tuy nhiên, bạn cần cân nhắc chi phí của việc sao chép so với việc tạo mới khi áp dụng mẫu này, vì việc sao chép có thể tốn nhiều tài nguyên hơn trong một số trường hợp. -------------------------------------------------------------------------------- /docs/Book/3. Structural Patterns.md: -------------------------------------------------------------------------------- 1 | # Structural Patterns 2 | 3 | > [!WARNING] 4 | > * Bài này sẽ được cập nhât ở [github sau](https://github.com/nguyenphuc22/Design-Patterns/blob/main/Writerside/topics/Structural-Patterns.md) và [website sau](https://nguyenphuc22.github.io/Design-Patterns/structural-patterns.html). 5 | > * File này sẽ được xoá vào cập nhật version_1 6 | 7 | 8 | Structural Patterns liên quan đến cấu trúc và mối quan hệ giữa các lớp và đối tượng nhằm tạo ra cấu trúc phần mềm dễ thay đổi và bảo trì hơn. 9 | 10 | Các Pattern thuộc nhóm này gồm: 11 | 12 | ## [Adapter](3.1%20Adapter.md) 13 | 14 | Cho phép giao tiếp giữa các interface không tương thích 15 | 16 | ## [Bridge](3.2%20Bridge.md) 17 | 18 | Tách rời một lớp phức tạp thành hai phần riêng biệt: trừu tượng và triển khai. 19 | 20 | ## [Composite](3.3%20Composite.md) 21 | 22 | Tạo ra cấu trúc cây để biểu diễn mối quan hệ whole-part giữa các đối tượng. 23 | 24 | ## [Decorator](3.4%20Decorator.md) 25 | 26 | Dynamically thêm chức năng mới cho đối tượng mà không ảnh hưởng đến các đối tượng khác. 27 | 28 | ## [Facade](3.5%20Facade.md) 29 | 30 | Cung cấp một giao diện đơn giản cho một nhóm các lớp phức tạp. 31 | 32 | ## [Flyweight](3.6%20Flyweight.md) 33 | 34 | Sử dụng chia sẻ để hỗ trợ tao hàng loạt các đối tượng hiệu quả hơn. 35 | 36 | ## [Proxy](3.7%20Proxy.md) 37 | 38 | Đại diện cho một đối tượng khác để kiểm soát truy cập vào đối tượng đó. 39 | 40 | Các Pattern này giải quyết vấn đề cấu trúc và mối quan hệ giữa các thành phần trong phần mềm để tối ưu hóa tính linh hoạt, bảo trì và tái sử dụng. -------------------------------------------------------------------------------- /docs/Book/4. Behavioral Patterns.md: -------------------------------------------------------------------------------- 1 | # Behavioral Patterns 2 | 3 | > [!WARNING] 4 | > * Bài này sẽ được cập nhât ở [github sau](https://github.com/nguyenphuc22/Design-Patterns/blob/main/Writerside/topics/Behavioral-Patterns.md) và [website sau](https://nguyenphuc22.github.io/Design-Patterns/behavioral-patterns.html). 5 | > * File này sẽ được xoá vào cập nhật version_1 6 | 7 | 8 | Behavioral Patterns liên quan đến cách giao tiếp và trao đổi thông tin giữa các đối tượng và lớp. Các Pattern thuộc nhóm này gồm: 9 | 10 | - , , , , , , , , , 11 | 12 | 13 | ## [Chain of Responsibility](4.1%20Chain%20of%20Responsibility.md) 14 | 15 | Cho phép chuyển các yêu cầu dọc theo chuỗi các đối tượng xử lý. 16 | 17 | ## [Command](4.2%20Command.md) 18 | 19 | Đóng gói yêu cầu thành các đối tượng có thể tham số hóa 20 | 21 | ## [Iterator](4.3%20Iterator.md) 22 | 23 | Truy cập tuần tự các phần tử một tập hợp dữ liệu 24 | 25 | ## [Mediator](4.4%20Mediator.md) 26 | 27 | Định nghĩa một đối tượng trung gian để giao tiếp giữa các đối tượng. 28 | 29 | ## [Memento](4.5%20Memento.md) 30 | 31 | ## [Observer](4.6%20Observer.md) 32 | 33 | Định nghĩa phụ thuộc một chiều giữa các đối tượng 34 | 35 | ## [State](4.7%20State.md) 36 | 37 | Cho phép một đối tượng thay đổi hành vi dựa trên trang thái nội bộ 38 | 39 | ## [Strategy](4.8%20Strategy.md) 40 | 41 | Định nghĩa tập các thuật toán có thể thay thế cho nhau để giải quyết một vấn đề. 42 | 43 | ## [Template Method](4.9%20Template%20Method.md) 44 | 45 | Định nghĩa bố cục xử lý chung cho một thuật toán, hoãn lại các bước cụ thể cho lớp con. 46 | 47 | ## [Visitor](4.10%20Visitor.md) 48 | 49 | Tách biệt các thuật toán khởi các đối tượng mà chúng hoạt động trên đó. 50 | 51 | -------------------------------------------------------------------------------- /docs/Book/4.1 Chain of Responsibility.md: -------------------------------------------------------------------------------- 1 | # Chain of Responsibility Pattern 2 | 3 | > [!WARNING] 4 | > * Bài này sẽ được cập nhât ở [github sau](https://github.com/nguyenphuc22/Design-Patterns/blob/main/Writerside/topics/Chain-Of-Responsibility.md) và [website sau](https://nguyenphuc22.github.io/Design-Patterns/chain-of-responsibility.html). 5 | > * File này sẽ được xoá vào cập nhật version_1 6 | 7 | 8 | ## Khái niệm 9 | 10 | **Chain of Responsibility** là Pattern thuộc nhóm hành vi (behavioral). Nó cho phép bản chuyển các yêu câu dọc theo 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 chuyển cho trình xử lý khác. 11 | 12 | ## Đặt vấn đề 13 | 14 | Bây giờ hãy tưởng tượng, bạn là một dev đang làm một hệ thống đặt hàng online. Bạn muốn hạn chế quyền truy cập vào hệ thống, chỉ những người đã xác thực mới có thể tạo đơn hàng. Đối với admin thì có toàn quền truy cập đơn của mọi người. 15 | 16 | ![](Images/problem.png) 17 | 18 | Sau một thời gian lên ý tưởng, bạn nhận các thao tác xác thực phải thực hiện tuần tự. Hệ thống sẽ xác thực người dùng khi người dùng đăng nhập, Tuy nhiên, nếu thông tin xác thực đó không thành công, thì không có lí do gì để thưc hiện các bước tiếp theo. 19 | 20 | Vài tháng sau, chức năng xác thực cần thêm vài case kiểm tra tuần tự nữa. 21 | 22 | - Có một anh đông nghiệp dể thương nào đấy nói với bạn rằng: "Em ơi, em chuyển dữ liệu thổ thẳng database hơi nguy hiểm nha em". Thế là bạn tiến một bước kiểm tra và lộc lại dữ liệu. 23 | - Vài tháng yên ắn sau đó, Có anh hacker mũ trắng nào đó bảo hệ thống của bạn quá yếu dể dàng bẻ khóa mật khẩu bằng brute force. Bạn nhận ra đó là sự thật, bạn vội thệm một lớp kiểm tra, lộc các yêu cầu lặp đi lặp lại không thành công nhưng có IP giống nhau và chặn nó. 24 | 25 | ![](Images/problem2.png) 26 | 27 | Theo thời gian, cái lớp xác thực của bạn càng ngày càng bự, nó trở thành mớ hỗn độn khó kiểm soát và mở rộng. Đặc biệt hơn, nếu ở những thành phần khác của hệ thống muốn dùng lại lớp xác thực, đây là điều không thể. Vì nhiều khi ở các thành phần khác chỉ cần sử một vài hàm nhỏ trong cái lớp xác thực bự đó. 28 | 29 | ## Giải pháp 30 | 31 | Chain of Responsibility dựa vào việc chuyển đổi các hành vi cụ thể thành các đối tượng hoạt động lập gọi là handlers. Trong vấn đề trên, với hoạt động kiểm thử bạn nên đổi chúng thành một lớp đối tượng cụ thể với một phương thức duy nhất là kiểm tra. 32 | 33 | ![](Images/solution.png) 34 | 35 | Mô hình gợi ý bạn liên kết các handlers lại thành một chuỗi. Như vậy, mỗi handlers phải lưu trữ tham chiếu đến handler tiếp theo, ngoài việc xử lý yêu cầu handlers còn có nhiệm vụ chuyện đến các handers tiếp theo. Yêu cầu sẽ chuyển theo hết chuỗi hoặc có thể kết thúc bật kì handlers nào. 36 | 37 | ## Cấu Trúc 38 | 39 | ![](Images/struct.png) 40 | 41 | - Handler: Định nghĩa 1 interface để xử lý các yêu cầu. 42 | - ConcreteHandler: Implement phương thức từ handler. 43 | - Client: Tạo ra các yêu cầu và yêu cầu đó sẽ được gửi đến các đối tượng tiếp nhận. 44 | 45 | ## Ví dụ áp dụng Chain of Responsibility 46 | 47 | ![](Images/vidu.png) 48 | 49 | Test.java 50 | 51 | ```java 52 | public abstract class Test { 53 | private Test next; 54 | 55 | public Test linkWith(Test next) { 56 | this.next = next; 57 | return next; 58 | } 59 | 60 | public abstract boolean check(String email, String password); 61 | 62 | 63 | protected boolean checkNext(String email, String password) { 64 | if (this.next == null) { 65 | return true; 66 | } 67 | return next.check(email, password); 68 | } 69 | } 70 | ``` 71 | 72 | RawDataTest.java 73 | 74 | ```java 75 | public class RawDataTest extends Test{ 76 | @Override 77 | public boolean check(String email, String password) { 78 | System.out.println("Raw Data"); 79 | if (!email.contains("@")) { 80 | System.out.println("Email Valid"); 81 | return false; 82 | } 83 | return this.checkNext(email,password); 84 | } 85 | } 86 | ``` 87 | 88 | RoleTest.java 89 | 90 | ```java 91 | public class RoleTest extends Test { 92 | @Override 93 | public boolean check(String email, String password) { 94 | System.out.println("Role Data"); 95 | if (email.equals("admin@example.com")) { 96 | System.out.println("Hello, admin!"); 97 | return true; 98 | } 99 | System.out.println("Hello, user!"); 100 | return checkNext(email, password); 101 | } 102 | } 103 | ``` 104 | 105 | UserExistsTest.java 106 | 107 | ```java 108 | public class UserExistsTest extends Test{ 109 | private Server server; 110 | 111 | public UserExistsTest(Server server) { 112 | this.server = server; 113 | } 114 | 115 | public boolean check(String email, String password) { 116 | System.out.println("User Exist"); 117 | if (!server.hasEmail(email)) { 118 | System.out.println("This email is not registered!"); 119 | return false; 120 | } 121 | 122 | return checkNext(email, password); 123 | } 124 | } 125 | ``` 126 | 127 | Server.java 128 | 129 | ```java 130 | import java.util.HashMap; 131 | import java.util.Map; 132 | 133 | public class Server { 134 | private Map users = new HashMap<>(); 135 | private Test test; 136 | 137 | public void setTest(Test test) { 138 | this.test = test; 139 | } 140 | 141 | public boolean hasEmail(String email) { 142 | return users.containsKey(email); 143 | } 144 | 145 | public void register(String email, String password) { 146 | users.put(email, password); 147 | } 148 | 149 | public boolean logIn(String email, String password) { 150 | if (this.test.check(email, password)) { 151 | System.out.println("Authorization have been successful!"); 152 | 153 | // Do something useful here for authorized users. 154 | 155 | return true; 156 | } 157 | System.out.println("Authorization have been fail!"); 158 | return false; 159 | } 160 | } 161 | ``` 162 | 163 | Demo.java 164 | 165 | ```java 166 | public class Demo { 167 | public static void main(String[] args) { 168 | Server server = new Server(); 169 | server.register("admin@example.com", "admin_pass"); 170 | server.register("phuc@xample.com", "user_pass"); 171 | 172 | Test test = new RawDataTest(); 173 | test.linkWith(new UserExistsTest(server)).linkWith(new RoleTest()); 174 | 175 | server.setTest(test); 176 | 177 | server.logIn("phuc@xample.com","user_pass"); 178 | System.out.println(); 179 | server.logIn("phucxample.com","user_pass"); 180 | System.out.println(); 181 | server.logIn("admin@example.com", "admin_pass"); 182 | 183 | } 184 | } 185 | ``` 186 | 187 | ## Khi nào áp dụng 188 | 189 | Sử dụng khi chương trình của bạn cần sử nhiều loại yêu cầu khác nhau, nhưng bạn chưa chưa xác định được loại yêu cầu và cách sắp xếp tuần tự của nó. 190 | 191 | Áp dụng khi một tác vụ nào đó cần sử lý tuần tự. 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /docs/Book/4.10 Visitor.md: -------------------------------------------------------------------------------- 1 | # Visitor Pattern 2 | 3 | > [!WARNING] 4 | > * Bài này sẽ được cập nhât ở [github sau](https://github.com/nguyenphuc22/Design-Patterns/blob/main/Writerside/topics/Visitor.md) và [website sau](https://nguyenphuc22.github.io/Design-Patterns/visitor.html). 5 | > * File này sẽ được xoá vào cập nhật version_1 6 | 7 | 8 | ## Giới thiệu 9 | 10 | Visitor Pattern cho phép thêm các thao tác mới vào cấu trúc đối tượng hiện có mà không cần thay đổi code. 11 | 12 | ## Định nghĩa 13 | 14 | Visitor Pattern tách biệt các thao tác cần thực hiện lên các đối tượng khỏi các đối tượng đó, bằng cách đưa logic vào một lớp Visitor riêng biệt. 15 | 16 | ## Mục đích 17 | 18 | - Cho phép thêm các thao tác mới lên cấu trúc đối tượng hiện có mà không cần thay đổi code. 19 | 20 | - Tách biệt các thao tác khỏi các đối tượng thực hiện chúng. 21 | 22 | ## Đặt vấn đề 23 | 24 | Giả sử bạn có một cấu trúc cây đối tượng phức tạp đại diện cho một tài liệu. Bây giờ cần thêm chức năng xuất tài liệu ra nhiều định dạng khác nhau (json, xml, pdf...). 25 | 26 | Làm thế nào để thêm chức năng mới mà không làm ảnh hưởng đến cấu trúc cây đối tượng hiện tại? 27 | 28 | ## Giải quyết 29 | 30 | Visitor Pattern được áp dụng như sau: 31 | 32 | - Định nghĩa một interface Visitor với các phương thức visit tương ứng với từng lớp Element. 33 | 34 | - Các lớp Element sẽ có phương thức accept nhận vào một Visitor. 35 | 36 | - Tạo các ConcreteVisitor triển khai các phương thức visit để thực hiện các thao tác cụ thể lên Element. 37 | 38 | ![](https://refactoring.guru/images/patterns/diagrams/visitor/structure.png) 39 | 40 | ## Cấu trúc 41 | 42 | Các thành phần chính trong Visitor Pattern: 43 | 44 | - Visitor: định nghĩa các phương thức thao tác trên các Element. 45 | 46 | - ConcreteVisitor: triển khai các phương thức trên. 47 | 48 | - Element: định nghĩa phương thức accept nhận vào một Visitor. 49 | 50 | - ConcreteElement: các lớp cụ thể cần áp dụng thao tác. 51 | 52 | ## Cách triển khai 53 | 54 | Để triển khai Visitor trong Java, ta có thể: 55 | 56 | - Định nghĩa interface Visitor với các phương thức visit tương ứng với từng Element. 57 | 58 | - Các Element có phương thức accept nhận vào một Visitor. 59 | 60 | - Các ConcreteVisitor triển khai các phương thức visit. 61 | 62 | ## Ví dụ 63 | 64 | // Ví dụ minh họa Visitor Pattern áp dụng cho việc xuất tài liệu 65 | 66 | ## So sánh với các Pattern 67 | 68 | So với Strategy, Visitor tách logic ra khỏi các đối tượng, trong khi Strategy nhóm các thuật toán lại với nhau. 69 | 70 | ## Kết luận 71 | 72 | Visitor Pattern giúp tách rời các thao tác khỏi các đối tượng thực thi, giúp dễ dàng bảo trì và mở rộng. Tuy nhiên cũng cần cân nhắc để tránh lạm dụng dẫn đến phức tạp code. -------------------------------------------------------------------------------- /docs/Book/4.2 Command.md: -------------------------------------------------------------------------------- 1 | # Command Pattern 2 | 3 | > [!WARNING] 4 | > * Bài này sẽ được cập nhât ở [github sau](https://github.com/nguyenphuc22/Design-Patterns/blob/main/Writerside/topics/Command.md) và [website sau](https://nguyenphuc22.github.io/Design-Patterns/command.html). 5 | > * File này sẽ được xoá vào cập nhật version_1 6 | 7 | 8 | ## Khái niệm 9 | 10 | **Command** là một Pattern dạng hành vi, cho phép biến một yêu cầu thành một đối tượng độc lập và chứa đầy đủ thông tin về yêu cầu đó. Nói cho dể hiểu, nó cho phép tất cả những Request gửi đến object được lưu trong chính object đó dưới dạng một object Command. 11 | 12 | ## Đặt vấn đề 13 | 14 | Giả sử bạn đang làm trên một ứng dụng soạn thảo văn bản mới. Công việc của bạn hiện tại là tạo một thanh toolbar với vài nút button để chỉnh sữa. Giờ bạn tạo một lớp cơ sở `Button` để sử dụng cho các nút button trên toolbar. 15 | 16 | Các nút button có vẻ rất giống nhau, nhưng sự kiện của từng nút thì lại khác nhau. Làm sao để gắn sự kiện cho từng nút button ? Cách đơn giản nhất là tạo các lớp riêng cho từng sự kiện và kế thừa lại lớp cơ sở `Button` 17 | 18 | ![](Images/problem.png) 19 | 20 | Sau một thời gian, bạn nhận ra rằng cách tiếp cận này rất thiêu sót. Đầu tiên, bạn có rất nhiều lớp con, và điều này vẫn ổn nếu như không phá mã trong các lớp khi lớp cơ sỡ `Button` thay đổi. 21 | 22 | Vấn đề tới nhất sẽ đến, khi ứng dụng của bạn phát triên cao hơn, người dùng không chỉ muốn nhấn vào các nút để thực hiện chức năng, mà còn thực hiện thông qua phím tắt hoặc vài thao tác kéo thả. Như vậy bạn phải một lớp khác bắt sự kiến phím tắt, sau đó lại copy toàn bộ chức năng ở nút `button` đã implement. Điều khá tốt những khi có việc cần thay đổi chức năng bạn phải cập nhật ở nhiều nơi. 23 | 24 | ## Giải pháp 25 | 26 | Để giải quyết vấn đề trên, ta sẽ tách phần giao diện và phần logic ra hai lớp khác nhau. Lớp GUI (Giao Diện) sẽ đảm nhiệm vài trò thể hiện các giao diện đẹp ra cho người dùng sử dung, đồng thời sẽ lắng nghe và bắt các sự khi người dùng sử dụng. Tuy nhiên, khi cần đến những việc tính toán, lưu trữ dữ liệu, hoặc truy vấn dữ liệu thì phần GUI nên giao lại cho phần logic đảm nhiệm. 27 | 28 | Nói đến đây các bạn sẽ nghỉ chỉ cần tách ra một lớp logic bắt và xử lý các logic các sử kiện nút `Button` thì đã xong. 29 | 30 | ![](Images/solution.png) 31 | 32 | Nhưng với Command Pattern đề nghị bạn đừng nên dùng GUI gọi yêu cầu trực tiếp. Bạn nên trích các thông tin, yêu cầu , tên phương được gọi......vào một lớp đặc biệt cùng với một phương thức để kích hoạt yêu cầu. 33 | 34 | ![](Images/solution2.png) 35 | 36 | Như vậy ta sẽ giảm được sử ghép nối giữa GUI và Logic, giúp bạn có thể Linh hoạt hơn trong sử dụng 37 | 38 | ## Cấu Trúc 39 | 40 | ![](Images/struct.png) 41 | 42 | - **Command**: là interface hoặc abstract class, chứa một phương thức duy nhất để executing lệnh. 43 | - **Concrete Command**: Thực hiện các yêu cầu khác nhau. Một Concrete Command không phải tự mình thực hiện công việc, thường sẽ chuyển đến lớp logic chuyên nghiệp. 44 | - **Client**: Tiếp nhận request từ phía người dùng, đống gói request thành ConcreteCommand thích hợp. 45 | - **Invoker**: Tiếp nhận Concrete Command từ Client và gọi execute() 46 | - **Receiver**: Đây là thành phần thực thi logic chuyên nghiệp. 47 | 48 | ## Ví dụ áp dụng Command Pattern 49 | 50 | ![](Images/vidu.png) 51 | 52 | Account.kt 53 | 54 | ```kotlin 55 | class Account { 56 | var name : String 57 | 58 | constructor(name: String) { 59 | this.name = name 60 | } 61 | 62 | fun open() { 63 | println("Account $name Opened") 64 | } 65 | 66 | fun close() { 67 | println("Account $name Closed") 68 | } 69 | 70 | } 71 | ``` 72 | 73 | Command.kt 74 | 75 | ```kotlin 76 | interface Command { 77 | fun execute() 78 | } 79 | ``` 80 | 81 | OpenAccount.kt 82 | 83 | ```kotlin 84 | class OpenAccount : Command{ 85 | var account: Account 86 | 87 | constructor(account: Account) { 88 | this.account = account 89 | } 90 | 91 | override fun execute() { 92 | account.open() 93 | } 94 | } 95 | ``` 96 | 97 | CloseAccount.kt 98 | 99 | ```kotlin 100 | class CloseAccount : Command { 101 | var account: Account 102 | 103 | constructor(account: Account) { 104 | this.account = account 105 | } 106 | 107 | 108 | override fun execute() { 109 | account.close() 110 | } 111 | } 112 | ``` 113 | 114 | BankApp.kt 115 | 116 | ```kotlin 117 | class BankApp { 118 | private var openAccount: Command? = null 119 | private var closeAccount: Command? = null 120 | 121 | constructor(openAccount: Command?, closeAccount: Command?) { 122 | this.openAccount = openAccount 123 | this.closeAccount = closeAccount 124 | } 125 | 126 | 127 | fun clickOpenAccount() { 128 | println("User click open an account") 129 | openAccount!!.execute() 130 | } 131 | 132 | fun clickCloseAccount() { 133 | println("User click close an account") 134 | closeAccount!!.execute() 135 | } 136 | } 137 | ``` 138 | 139 | main.kt 140 | 141 | ```kotlin 142 | fun main(args: Array) { 143 | var account : Account = Account("NickSeven") 144 | 145 | var openAccount : Command = OpenAccount(account) 146 | 147 | var closeAccount : Command = CloseAccount(account) 148 | 149 | var bankApp : BankApp = BankApp(openAccount,closeAccount) 150 | 151 | bankApp.clickOpenAccount() 152 | 153 | bankApp.clickCloseAccount() 154 | } 155 | ``` 156 | 157 | Kết quả 158 | 159 | ``` 160 | User click open an account 161 | Account NickSeven Opened 162 | User click close an account 163 | Account NickSeven Closed 164 | 165 | Process finished with exit code 0 166 | ``` 167 | 168 | ## Khi nào áp dụng 169 | 170 | Khi cần tham số hóa các đối tượng theo một hành động thực hiện. 171 | 172 | Khi cần tạo và thực thi các yêu cầu vào các thời điểm khác nhau. -------------------------------------------------------------------------------- /docs/Book/4.3 Iterator.md: -------------------------------------------------------------------------------- 1 | # Iterator 2 | 3 | > [!WARNING] 4 | > * Bài này sẽ được cập nhât ở [github sau](https://github.com/nguyenphuc22/Design-Patterns/blob/main/Writerside/topics/Iterator.md) và [website sau](https://nguyenphuc22.github.io/Design-Patterns/iterator.html). 5 | > * File này sẽ được xoá vào cập nhật version_1 6 | 7 | 8 | ## Khái niệm 9 | 10 | `Iterator` một mẫu pattern hành vi nó cho phép bạn duyệt qua các phần tử của bộ sưu tập ( collection ) mà không cần quan tâm tới cấu trúc của nó (list, stack, tree, etc....). 11 | 12 | ## Đặt vấn đề 13 | 14 | `Collections` là một kiểu dữ liệu được sử dụng nhiều nhất trong lập trình. Tuy nhiên, `Collection` chỉ là một mảng nhóm các đối tượng lại với nhau. 15 | 16 | Hầu hết `collections` sẽ lưu trữ các phần tử của chúng một cách rất đơn giản. Tuy nhiên lại, tồn tại một số `collection` có cách lưu trữ rất phức tạp như stacks, trees, graphs và một số cấu trúc dữ liệu phức tạp khác. 17 | 18 | Dù thế nào, `collections` phải cung cấp các phương thức để truy vấn đến các phần từ mà chúng lưu trữ. Cần có một cách nào đó để duyệt qua các phần tử mà không cần phải truy cập lại cấc phần tử giống nhau. 19 | 20 | Nghe thì có vẻ dể nếu `collection` đang dùng là dạng list. Việt duyệt qua các phần tử rất dể, chỉ đơn giản dùng một dòng for. Nhưng nếu đó là một `collection` dạng phức tạp hơn thì sao ? Ví dụ như dạng cây chẳng hạn. Ban đầu bạn phải duyệt theo chiều sâu (depth-first) nhưng một ngày đẹp trời khác bạn lại phải duyệt theo chiều rộng (breadth-first). Một tháng sau, bạn truy vấn đến phần tử ngẫu nhiên. Điều này nghe lại không hề dể tí nào. 21 | 22 | ## Giải pháp 23 | 24 | Ý tưởng chính của `Iterator` pattern là lấy hành vi duyệt phần tự của `collection` tách no ra thành một object riêng gọi là một iterator. 25 | 26 | ![](Images/solution.PNG) 27 | 28 | Ngoài việc implementing thuật toán, một đối tượng `iterator` có thể đống gói toàn bộ những chi tiết về quá trình duyệt như: vị trí hiện tại và còn bao nhiêu phần tử nữa thì kết thúc. 29 | 30 | ## Cấu Trúc 31 | 32 | ![](Images/struct.PNG) 33 | 34 | - **Iterator** : là một interface hoặc abstract class khai báo các hoạt động cần thiết để duyệt qua các phần tử. 35 | - **Concrete Iterators** : cài đặt các phương thức của Iterator, giữ index khi duyệt qua các phần tử. 36 | - **Iterable Collection** : là một interface tạo ra một hoặc nhiều phương thức cho để lấy `interators` tương thích với `Collection`. 37 | - **Concrete Collections** : cài đặt các phương thức Iterable Collection, nó cái đặt interface tạo Iterator trả về một Concrete Iterators thích hợp. 38 | - **Client** : Đối tượng sử dụng Iterator Pattern. 39 | 40 | ## Ví dụ áp dụng Iterator Collection 41 | 42 | ![](Images/Vidu.PNG) 43 | 44 | Item.java 45 | 46 | ```java 47 | public class Item { 48 | private String name; 49 | private int age; 50 | 51 | public Item(String name, int age) { 52 | this.name = name; 53 | this.age = age; 54 | } 55 | 56 | @Override 57 | public String toString() { 58 | return "Item{" + 59 | "name='" + name + '\'' + 60 | ", age=" + age + 61 | '}'; 62 | } 63 | } 64 | ``` 65 | 66 | ItemIterator.java 67 | 68 | ```java 69 | public interface ItemIterator { 70 | 71 | boolean hasNext(); 72 | 73 | T next(); 74 | 75 | } 76 | ``` 77 | 78 | IterableCollection.java 79 | 80 | ```java 81 | public interface IterableCollection { 82 | 83 | void addItem(T temp); 84 | 85 | ItemIterator iterator(); 86 | 87 | } 88 | ``` 89 | 90 | MenuCollection.java 91 | 92 | ```java 93 | import java.util.ArrayList; 94 | import java.util.List; 95 | 96 | public class MenuCollection implements IterableCollection { 97 | 98 | private List menuItem = new ArrayList<>(); 99 | 100 | public MenuCollection(List menuItem) { 101 | this.menuItem = menuItem; 102 | } 103 | 104 | @Override 105 | public void addItem(Object temp) { 106 | menuItem.add((T) temp); 107 | } 108 | 109 | @Override 110 | public ItemIterator iterator() { 111 | return new MenuItemIterator(); 112 | } 113 | 114 | class MenuItemIterator implements ItemIterator { 115 | private int currentIndex = 0; 116 | 117 | @Override 118 | public boolean hasNext() { 119 | return currentIndex < menuItem.size(); 120 | } 121 | 122 | @Override 123 | public T next() { 124 | return menuItem.get(currentIndex++); 125 | } 126 | } 127 | } 128 | ``` 129 | 130 | demo.java 131 | 132 | ```java 133 | import java.util.ArrayList; 134 | import java.util.List; 135 | 136 | public class demo { 137 | public static void main(String[] args) { 138 | 139 | List list = new ArrayList<>(); 140 | list.add(new Item("Phuc",18)); 141 | list.add(new Item("An",19)); 142 | list.add(new Item("Nam",20)); 143 | list.add(new Item("Bang",21)); 144 | 145 | 146 | IterableCollection collection = new MenuCollection(list); 147 | collection.addItem(new Item("Nick",10)); 148 | collection.addItem(new Item("Tick", 20)); 149 | 150 | ItemIterator itemIterator = collection.iterator(); 151 | 152 | while (itemIterator.hasNext()) { 153 | Item item = (Item) itemIterator.next(); 154 | System.out.println(item.toString()); 155 | } 156 | } 157 | } 158 | ``` 159 | 160 | ## Khi nào nên sử dụng 161 | 162 | Sử dụng khi `collection` của bạn có cấu trúc phức tạp và bạn không muốn ẩn nó đi, không muốn cho clients của mình biết đến. 163 | 164 | Sử dụng để giảm thiểu các mã trung lập khi duyệt phần tử. -------------------------------------------------------------------------------- /docs/Book/4.4 Mediator.md: -------------------------------------------------------------------------------- 1 | # Mediator Pattern 2 | 3 | > [!WARNING] 4 | > * Bài này sẽ được cập nhât ở [github sau](https://github.com/nguyenphuc22/Design-Patterns/blob/main/Writerside/topics/Mediator.md) và [website sau](https://nguyenphuc22.github.io/Design-Patterns/mediator.html). 5 | > * File này sẽ được xoá vào cập nhật version_1 6 | 7 | 8 | ## Giới thiệu 9 | 10 | Mediator Pattern định nghĩa một đối tượng trung gian (mediator) để điều phối tương tác giữa các đối tượng, làm giảm sự phụ thuộc trực tiếp giữa chúng. 11 | 12 | ## Định nghĩa 13 | 14 | Mediator Pattern định nghĩa một đối tượng Mediator đóng vai trò trung gian điều phối giao tiếp giữa các đối tượng, tránh cho chúng phải giao tiếp trực tiếp với nhau. 15 | 16 | ## Mục đích 17 | 18 | - Giảm sự phụ thuộc trực tiếp giữa các đối tượng 19 | 20 | - Tách biệt cách các đối tượng giao tiếp với nhau 21 | 22 | - Dễ dàng mở rộng và thay đổi cách giao tiếp giữa các lớp 23 | 24 | ## Đặt vấn đề 25 | 26 | Giả sử bạn đang phát triển một ứng dụng nhắn tin với các đối tượng User và ChatRoom. Ban đầu, mỗi User giao tiếp trực tiếp với ChatRoom để gửi tin nhắn. 27 | 28 | Sau này, yêu cầu thay đổi là cần kiểm duyệt tin nhắn trước khi gửi đi. Lúc này, mối phụ thuộc trực tiếp giữa các đối tượng dẫn tới khó khăn trong việc thay đổi. 29 | 30 | ## Giải quyết 31 | 32 | Mediator Pattern được áp dụng như sau: 33 | 34 | - Định nghĩa một lớp Mediator đóng vai trò trung gian điều phối giữa các User và ChatRoom. 35 | 36 | - Các User và ChatRoom không giao tiếp trực tiếp với nhau nữa mà thông qua Mediator. 37 | 38 | - Khi có yêu cầu thay đổi, ta chỉ cần sửa đổi bên trong Mediator mà không ảnh hưởng các User và ChatRoom. 39 | 40 | ![](https://refactoring.guru/images/patterns/diagrams/mediator/structure.png) 41 | 42 | ## Cấu trúc 43 | 44 | Các thành phần chính trong Mediator Pattern: 45 | 46 | - Mediator: định nghĩa interface để giao tiếp với các Colleague. 47 | 48 | - Colleague: giao tiếp với mediator thay vì giao tiếp trực tiếp với các Colleague khác. 49 | 50 | - ConcreteMediator: triển khaiMediator để điều phối các Colleague. 51 | 52 | - ConcreteColleague: các lớp cụ thể tương tác với mediator. 53 | 54 | ## Cách triển khai 55 | 56 | Để triển khai Mediator Pattern trong Java, chúng ta có thể: 57 | 58 | - Định nghĩa interface Mediator với các phương thức trung gian. 59 | 60 | - Các lớp Colleague sẽ giữ một tham chiếu tới Mediator và gọi các phương thức đó thay vì giao tiếp trực tiếp. 61 | 62 | - Lớp ConcreteMediator sẽ triển khai và điều phối các interation giữa các Colleague. 63 | 64 | ## Ví dụ 65 | 66 | // Ví dụ triển khai Mediator Pattern với các lớp ChatRoom, User 67 | 68 | ## So sánh 69 | 70 | So với Observer, Mediator tập trung vào việc điều phối giao tiếp giữa các đối tượng, còn Observer tập trung vào mối quan hệ một-nhiều giữa các đối tượng. 71 | 72 | ## Kết luận 73 | 74 | Mediator Pattern hữu ích để giảm sự phụ thuộc trực tiếp giữa các lớp, dễ dàng mở rộng và thay đổi chương trình. Tuy nhiên cũng cần tránh lạm dụng mediator dẫn tới phức tạp hóa code. -------------------------------------------------------------------------------- /docs/Book/4.5 Memento.md: -------------------------------------------------------------------------------- 1 | # Memento Pattern 2 | 3 | > [!WARNING] 4 | > * Bài này sẽ được cập nhât ở [github sau](https://github.com/nguyenphuc22/Design-Patterns/blob/main/Writerside/topics/Memento.md) và [website sau](https://nguyenphuc22.github.io/Design-Patterns/memento.html). 5 | > * File này sẽ được xoá vào cập nhật version_1 6 | 7 | 8 | ## Giới thiệu 9 | 10 | Memento Pattern cung cấp khả năng lưu và khôi phục trạng thái trước đó của một đối tượng mà không vi phạm encapsulation. 11 | 12 | ## Định nghĩa 13 | 14 | Memento Pattern lưu trữ trạng thái nội bộ của một đối tượng vào một đối tượng riêng biệt được gọi là Memento. Đối tượng ban đầu có thể khôi phục lại trạng thái từ Memento. 15 | 16 | ## Mục đích 17 | 18 | - Lưu lại và khôi phục trạng thái của một đối tượng mà không vi phạm encapsulation. 19 | 20 | - Cung cấp khả năng hoàn tác (undo/rollback) trong quá trình thao tác với đối tượng. 21 | 22 | ## Đặt vấn đề 23 | 24 | Giả sử bạn đang phát triển một trò chơi có đối tượng Player đại diện cho người chơi. Trong quá trình chơi, trạng thái của Player (vị trí, máu, điểm,..) liên tục thay đổi. 25 | 26 | Để người chơi có thể quay lại trạng thái trước đó khi cần thiết, chúng ta cần lưu lại các trạng thái đó một cách hiệu quả. Đồng thời, không làm ảnh hưởng tới encapsulation của lớp Player. 27 | 28 | ## Giải quyết 29 | 30 | Memento Pattern giải quyết bài toán trên bằng cách: 31 | 32 | - Tạo ra một lớp Memento để lưu trữ trạng thái của đối tượng. Memento chỉ lưu trữ dữ liệu, không có hành vi. 33 | 34 | - Lớp Player tạo ra đối tượng Memento chứa trạng thái của nó, và có thể khôi phục lại trạng thái từ Memento. 35 | 36 | - Originator không truy cập trực tiếp vào Memento, mà thông qua Caretaker. 37 | 38 | ![](https://refactoring.guru/images/patterns/diagrams/memento/structure.png) 39 | 40 | ## Cấu trúc 41 | 42 | Các thành phần trong Memento Pattern: 43 | 44 | - Originator: đối tượng cần lưu trữ trạng thái. 45 | 46 | - Memento: đối tượng lưu trữ trạng thái của Originator. 47 | 48 | - Caretaker: quản lý các đối tượng Memento. 49 | 50 | ## Cách triển khai 51 | 52 | Để triển khai Memento Pattern trong Java, chúng ta có thể: 53 | 54 | - Tạo lớp Memento với các trường dữ liệu cần lưu trữ. 55 | 56 | - Lớp Originator sẽ tạo ra đối tượng Memento và lưu/khôi phục trạng thái từ nó. 57 | 58 | - Caretaker sẽ quản lý các Memento. 59 | 60 | ## Ví dụ 61 | 62 | // Ví dụ triển khai Memento Pattern để lưu trạng thái đối tượng Player trong game. 63 | 64 | ## So sánh với các Pattern khác 65 | 66 | So với Iterator, Memento tập trung vào việc lưu trữ trạng thái nội bộ của một đối tượng, còn Iterator tập trung vào việc truy cập tuần tự các phần tử trong bộ sưu tập. 67 | 68 | ## Kết luận 69 | 70 | Memento Pattern rất hữu ích khi muốn lưu lại và khôi phục trạng thái của đối tượng mà không vi phạm encapsulation. Tuy nhiên cũng cần xem xét chi phí về bộ nhớ khi lưu trữ nhiều snapshot. -------------------------------------------------------------------------------- /docs/Book/4.6 Observer.md: -------------------------------------------------------------------------------- 1 | # Observer Pattern 2 | 3 | > [!WARNING] 4 | > * Bài này sẽ được cập nhât ở [github sau](https://github.com/nguyenphuc22/Design-Patterns/blob/main/Writerside/topics/Observer.md) và [website sau](https://nguyenphuc22.github.io/Design-Patterns/observer.html). 5 | > * File này sẽ được xoá vào cập nhật version_1 6 | 7 | 8 | ## Giới thiệu 9 | 10 | Observer Pattern định nghĩa mối phụ thuộc một-nhiều giữa các đối tượng để khi một đối tượng thay đổi trạng thái, các đối tượng phụ thuộc vào nó sẽ được thông báo và cập nhật. 11 | 12 | ## Định nghĩa 13 | 14 | Observer Pattern mô tả mối quan hệ giữa các đối tượng theo mô hình phát trực tiếp (publish-subscribe), trong đó có một đối tượng (subject) sẽ "báo cáo" sự thay đổi trạng thái của nó tới các đối tượng đăng ký quan sát (observer) để chúng cập nhật. 15 | 16 | ## Mục đích 17 | 18 | - Định nghĩa mối phụ thuộc một-nhiều giữa các đối tượng. 19 | 20 | - Khi một đối tượng thay đổi trạng thái, tất cả các đối tượng phụ thuộc vào nó sẽ được thông báo và cập nhật. 21 | 22 | ## Đặt vấn đề 23 | 24 | Giả sử bạn đang phát triển một website thương mại điện tử với các chức năng sau: 25 | 26 | - Người dùng có thể đăng ký nhận thông báo khi một sản phẩm nào đó có giá giảm. 27 | 28 | - Khi giá sản phẩm thay đổi, tất cả người dùng đã đăng ký sẽ nhận được thông báo. 29 | 30 | Làm thế nào để triển khai khi có hàng triệu người dùng cùng theo dõi hàng triệu sản phẩm khác nhau? 31 | 32 | ## Giải quyết 33 | 34 | Observer Pattern được áp dụng như sau: 35 | 36 | - Định nghĩa một Subject (đối tượng chủ đề) đại diện cho sản phẩm. 37 | 38 | - Người dùng (Observer) có thể đăng ký theo dõi Subject. 39 | 40 | - Khi trạng thái của Subject thay đổi (giá sản phẩm) thì sẽ thông báo tới tất cả Observer đã đăng ký. 41 | 42 | ![](https://refactoring.guru/images/patterns/diagrams/observer/structure.png) 43 | 44 | ## Cấu trúc 45 | 46 | Các thành phần trong Observer Pattern: 47 | 48 | - Subject: đối tượng chủ thể cần theo dõi. Nó duy trì danh sách các Observer và thông báo cho chúng khi trạng thái thay đổi. 49 | 50 | - Observer: đối tượng quan sát Subject. Nó đăng ký theo dõi Subject và cập nhật khi nhận được thông báo từ Subject. 51 | 52 | - ConcreteSubject và ConcreteObserver: các cài đặt cụ thể. 53 | 54 | ## Cách triển khai 55 | 56 | Để triển khai Observer Pattern trong Java, có thể: 57 | 58 | - Sử dụng interface java.util.Observable và java.util.Observer. 59 | - Tự định nghĩa Subject, Observer interface và các cài đặt tương ứng. 60 | 61 | ## Ví dụ 62 | 63 | // Ví dụ đăng ký nhận thông báo khi giá sản phẩm thay đổi 64 | 65 | ## So sánh 66 | 67 | So với PubSub, Observer tập trung vào mối quan hệ giữa các object, còn PubSub tập trung vào việc truyền thông điệp. 68 | 69 | ## Kết luận 70 | 71 | Observer Pattern thích hợp để xây dựng các chức năng thông báo sự kiện trong hệ thống. Tuy nhiên cũng cần tránh lạm dụng và làm phức tạp hóa code. -------------------------------------------------------------------------------- /docs/Book/4.7 State.md: -------------------------------------------------------------------------------- 1 | # State Pattern 2 | 3 | > [!WARNING] 4 | > * Bài này sẽ được cập nhât ở [github sau](https://github.com/nguyenphuc22/Design-Patterns/blob/main/Writerside/topics/State.md) và [website sau](https://nguyenphuc22.github.io/Design-Patterns/state.html). 5 | > * File này sẽ được xoá vào cập nhật version_1 6 | 7 | 8 | ## Giới thiệu 9 | 10 | State Pattern cho phép một đối tượng thay đổi hành vi của nó khi trạng thái nội bộ thay đổi. Điều này được thực hiện bằng cách đóng gói trạng thái vào các lớp riêng biệt. 11 | 12 | ## Định nghĩa 13 | 14 | State Pattern định nghĩa trạng thái của một đối tượng như một lớp riêng biệt. Khi trạng thái thay đổi, đối tượng sẽ thay đổi lớp hiện tại của nó bằng một lớp mới để thay đổi hành vi. 15 | 16 | ## Mục đích 17 | 18 | - Cho phép một đối tượng thay đổi hành vi khi trạng thái nội bộ thay đổi. 19 | 20 | - Đóng gói các trạng thái và hành vi liên quan vào các lớp riêng biệt. 21 | 22 | - Tách biệt máy trạng thái khỏi ngữ cảnh sử dụng nó. 23 | 24 | ## Đặt vấn đề 25 | 26 | Giả sử bạn đang phát triển một trò chơi, có lớp NhânVật có các trạng thái: đi bộ, chạy, nhảy. Mỗi trạng thái sẽ có các hành vi riêng. 27 | 28 | Ban đầu, mọi logic xử lý được đặt trong lớp NhânVật dẫn đến lớp này phình to, khó bảo trì. 29 | 30 | Làm thế nào để tổ chức code cho dễ quản lý hơn? 31 | 32 | ## Giải quyết 33 | 34 | State Pattern được áp dụng như sau: 35 | 36 | - Mỗi trạng thái được đóng gói thành một lớp riêng biệt, triển khai từ một interface chung. 37 | 38 | - Lớp NhânVật sẽ lưu trữ trạng thái hiện tại và delegate mọi hành vi cho trạng thái đó. 39 | 40 | - Khi trạng thái thay đổi, NhânVật sẽ chuyển sang trạng thái mới. 41 | 42 | ![](https://refactoring.guru/images/patterns/diagrams/state/structure.png) 43 | 44 | ## Cấu trúc 45 | 46 | Các thành phần chính trong State Pattern: 47 | 48 | - Context: lớp chứa tham chiếu đến trạng thái hiện tại. 49 | 50 | - State: interface chung cho các trạng thái. 51 | 52 | - ConcreteState: các lớp triển khai cụ thể cho mỗi trạng thái. 53 | 54 | ## Cách triển khai 55 | 56 | Để triển khai State Pattern trong Java, chúng ta có thể: 57 | 58 | - Định nghĩa một interface chung cho State. 59 | 60 | - Tạo các lớp Concrete State triển khai interface đó. 61 | 62 | - Lớp Context sẽ lưu trữ instance của State hiện tại. 63 | 64 | ## Ví dụ 65 | 66 | // Ví dụ State Pattern áp dụng cho trạng thái của nhân vật trong game 67 | 68 | ## So sánh với các Pattern 69 | 70 | So với Strategy, State tập trung vào việc thay đổi hành vi dựa trên trạng thái đối tượng. Strategy tập trung vào việc thay đổi thuật toán riêng lẻ. 71 | 72 | ## Kết luận 73 | 74 | State Pattern giúp tổ chức code dựa trên trạng thái của đối tượng, dễ mở rộng và bảo trì hơn. Tuy nhiên cũng cần tránh lạm dụng và làm phức tạp hóa code. -------------------------------------------------------------------------------- /docs/Book/4.8 Strategy.md: -------------------------------------------------------------------------------- 1 | # Strategy Pattern 2 | 3 | > [!WARNING] 4 | > * Bài này sẽ được cập nhât ở [github sau](https://github.com/nguyenphuc22/Design-Patterns/blob/main/Writerside/topics/Strategy.md) và [website sau](https://nguyenphuc22.github.io/Design-Patterns/strategy.html). 5 | > * File này sẽ được xoá vào cập nhật version_1 6 | 7 | 8 | ## Giới thiệu 9 | 10 | Strategy Pattern định nghĩa một nhóm các thuật toán có thể hoán đổi cho nhau để thay đổi thuật toán bên trong một đối tượng tại runtime. 11 | 12 | ## Định nghĩa 13 | 14 | Strategy Pattern định nghĩa tập hợp các thuật toán có thể thay thế cho nhau và cung cấp cách để client có thể dễ dàng thay đổi các thuật toán này độc lập với ngữ cảnh sử dụng. 15 | 16 | ## Mục đích 17 | 18 | - Tách biệt thuật toán riêng lẻ thành các lớp độc lập. 19 | 20 | - Các thuật toán có thể hoán đổi cho nhau dễ dàng. 21 | 22 | - Tránh sử dụng các câu lệnh điều kiện phức tạp. 23 | 24 | ## Đặt vấn đề 25 | 26 | Giả sử bạn đang phát triển một game, có lớp NhânVật có phương thức diChuyển(). Ban đầu chỉ có cách di chuyển bằng đi bộ. Sau này có thêm yêu cầu bay và bơi. 27 | 28 | Nếu đặt tất cả các cách di chuyển vào lớp NhânVật sẽ dẫn đến lớp này bị phình to, khó bảo trì. 29 | 30 | Làm thế nào để dễ dàng thêm mới cách di chuyển mà không ảnh hưởng đến lớp NhânVật? 31 | 32 | ## Giải quyết 33 | 34 | Strategy Pattern được áp dụng như sau: 35 | 36 | - Mỗi thuật toán di chuyển được đóng gói thành một lớp riêng biệt, triển khai từ một interface. 37 | 38 | - Lớp NhânVật sẽ lưu trữ một tham chiếu tới interface di chuyển. 39 | 40 | - Khi cần thay đổi thuật toán, chỉ cần gán lớp triển khai mới cho tham chiếu đó. 41 | 42 | ![](https://refactoring.guru/images/patterns/diagrams/strategy/structure.png) 43 | 44 | ## Cấu trúc 45 | 46 | Các thành phần chính trong Strategy Pattern: 47 | 48 | - Strategy: interface chung cho các thuật toán. 49 | 50 | - ConcreteStrategy: các lớp triển khai cụ thể các thuật toán. 51 | 52 | - Context: lớp sử dụng các thuật toán thông qua Strategy. 53 | 54 | ## Cách triển khai 55 | 56 | Để triển khai Strategy Pattern trong Java, chúng ta có thể: 57 | 58 | - Định nghĩa một interface chung cho Strategy. 59 | 60 | - Các ConcreteStrategy triển khai interface đó. 61 | 62 | - Context sẽ có một tham chiếu tới Strategy và sử dụng nó. 63 | 64 | ## Ví dụ 65 | 66 | // Ví dụ minh họa Strategy Pattern áp dụng cho cách di chuyển của nhân vật 67 | 68 | ## So sánh với các Pattern 69 | 70 | So với State, Strategy tập trung vào việc thay đổi riêng lẻ một thuật toán cụ thể, còn State tập trung vào việc thay đổi toàn bộ hành vi dựa trên trạng thái. 71 | 72 | ## Kết luận 73 | 74 | Strategy Pattern giúp tách biệt các thuật toán riêng lẻ thành các lớp độc lập, dễ dàng thay đổi và mở rộng. Tuy nhiên cũng cần tránh lạm dụng dẫn đến phức tạp code. -------------------------------------------------------------------------------- /docs/Book/4.9 Template Method.md: -------------------------------------------------------------------------------- 1 | # Template Method Pattern 2 | 3 | > [!WARNING] 4 | > * Bài này sẽ được cập nhât ở [github sau](https://github.com/nguyenphuc22/Design-Patterns/blob/main/Writerside/topics/Template-Method.md) và [website sau](https://nguyenphuc22.github.io/Design-Patterns/template-method.html). 5 | > * File này sẽ được xoá vào cập nhật version_1 6 | 7 | 8 | ## Giới thiệu 9 | 10 | Template Method Pattern định nghĩa bố cục của một thuật toán trong một phương thức, nhưng để các bước cụ thể của thuật toán được các lớp con cài đặt lại. 11 | 12 | ## Định nghĩa 13 | 14 | Template Method Pattern định nghĩa khung của một thuật toán trong một phương thức, nhưng cho phép các lớp con ghi đè lại các bước cụ thể của thuật toán đó mà không thay đổi cấu trúc chung. 15 | 16 | ## Mục đích 17 | 18 | - Định nghĩa bố cục chung của một thuật toán. 19 | 20 | - Cho phép các lớp con cài đặt lại các bước cụ thể mà không làm thay đổi bố cục. 21 | 22 | - Giảm sự lặp lại code giữa các lớp có cùng bố cục thuật toán. 23 | 24 | ## Đặt vấn đề 25 | 26 | Giả sử bạn cần xây dựng một ứng dụng có khả năng xuất dữ liệu ra nhiều định dạng khác nhau (csv, xml, json...). 27 | 28 | Các bước xuất dữ liệu đều tương tự nhau, nhưng định dạng output thì khác nhau. Việc copy-paste code sẽ dẫn tới khó khăn trong bảo trì sau này. 29 | 30 | ## Giải quyết 31 | 32 | Template Method được áp dụng như sau: 33 | 34 | - Định nghĩa một lớp Abstract chứa phương thức template method định nghĩa bố cục chung của thuật toán. 35 | 36 | - Cài đặt các bước trừu tượng trong template method. 37 | 38 | - Các lớp con sẽ cài đặt lại các bước trừu tượng này. 39 | 40 | ![](https://refactoring.guru/images/patterns/diagrams/template-method/structure.png) 41 | 42 | ## Cấu trúc 43 | 44 | Các thành phần chính trong Template Method Pattern: 45 | 46 | - AbstractClass: định nghĩa template method và các phương thức trừu tượng. 47 | 48 | - ConcreteClass: cài đặt lại các phương thức trừu tượng. 49 | 50 | ## Cách triển khai 51 | 52 | Để triển khai Template Method trong Java, chúng ta có thể: 53 | 54 | - Tạo một abstract class khai báo các phương thức trừu tượng. 55 | 56 | - Cài đặt một template method sử dụng các phương thức trừu tượng đó. 57 | 58 | - Các lớp con sẽ cài đặt lại các phương thức trừu tượng. 59 | 60 | ## Ví dụ 61 | 62 | // Ví dụ Template Method áp dụng cho export dữ liệu có định dạng khác nhau 63 | 64 | ## So sánh với các Pattern 65 | 66 | So với Strategy, Template Method định nghĩa bố cục của thuật toán và gọi các phương thức trừu tượng. Strategy định nghĩa riêng các thuật toán có thể hoán đổi cho nhau. 67 | 68 | ## Kết luận 69 | 70 | Template Method giúp tái sử dụng code và tránh lặp lại phần khung của thuật toán giữa các lớp. Tuy nhiên cần cân nhắc khi sử dụng để tránh phức tạp hóa code. -------------------------------------------------------------------------------- /docs/Book/5. Read World.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/Book/5. Read World.md -------------------------------------------------------------------------------- /docs/Book/6. Conclusion.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/Book/6. Conclusion.md -------------------------------------------------------------------------------- /docs/Book/Struct.md: -------------------------------------------------------------------------------- 1 | # Dàn ý cho Viết về Một Design Pattern 2 | 3 | ## Tên của Pattern 4 | 5 | ### Giới thiệu (1-2 đoạn) 6 | - **Định nghĩa của Pattern**: Định nghĩa ngắn gọn bao hàm bản chất của pattern. 7 | - **Mục đích**: Mục tiêu chính và vấn đề mà nó giải quyết. 8 | - **Ý tưởng Cốt lõi**: Giải thích về khái niệm cơ bản hoặc chiến lược mà pattern sử dụng. 9 | 10 | ### Đặt vấn đề (1-2 đoạn) 11 | - **Bối cảnh**: Mô tả tình huống tiêu biểu, khó khăn mà khi không sử dụng pattern này. 12 | - **Sơ đồ mình hoạ**: Cho sơ đồng minh hoạ đươc vẻ bằng mermaid. 13 | 14 | ### Giải pháp (2-3 đoạn) 15 | - **Cách tiếp cận**: Pattern giải quyết những vấn đề đã nêu trong phần "Vấn đề" như thế nào. 16 | - **Lợi ích**: Những ưu điểm khi sử dụng pattern. 17 | - **Sự đánh đổi**: Bất kỳ sự thỏa hiệp hoặc chi phí nào liên quan trong việc thực hiện pattern. 18 | - **Sơ đồ minh hoạ**: Cho sơ đồng minh hoạ đươc vẻ bằng mermaid. 19 | 20 | ### Cấu trúc (1-2 đoạn, 1 sơ đồ) 21 | 22 | - **Sơ đồ**: Sơ đồ lớp hoặc sơ đồ tuần tự thể hiện cấu trúc của pattern một cách trực quan. 23 | - **Các thành phần**: Liệt kê và mô tả các bộ phận của pattern. 24 | - **Tổ chức và Tương tác**: Cách các thành phần được tổ chức và tương tác với nhau. 25 | 26 | ### Triển khai (3-5 đoạn, đoạn code) 27 | - **Các Chiến lược Triển khai**: Bàn luận về các cách triển khai pattern khác nhau. 28 | - **Đoạn Code**: Cung cấp ví dụ code cụ thể trong một hoặc nhiều ngôn ngữ lập trình. 29 | - **Cân nhắc**: Đề cập đến các điều cần xem xét khi triển khai. 30 | 31 | ### Ví dụ (2-3 đoạn, giải thích, sở đồ, ví dụ code) 32 | - **Giải thích**: Giới thiệu về ví dụ của pattern, giải thích rõ ràng ví dụ 33 | - **Sơ đồ**: Cho một sơ đồ được vẻ bằng mermaid, thể hiện ví dụ. 34 | - **Ví dụ Code**: Một ví dụ từng bước hiển thị pattern được áp dụng theo lời giải thích. 35 | 36 | ### So sánh (2-3 đoạn) 37 | - **So sánh với Các Pattern Khác**: Điểm nổi bật, các khác biệt và điểm tương đồng của pattern đang viết với các design pattern khác. 38 | - **Khi nào Sử dụng**: Các tình huống mà pattern này được ưa chuộng hơn các pattern khác. 39 | 40 | ### Chú ý (1-2 đoạn) 41 | - **Cẩn trọng**: Chỉ ra những sai lầm thường gặp và cách tránh chúng. 42 | - **Thực hành Tốt nhất**: Chia sẻ kinh nghiệm về các phương pháp tốt đã rút ra từ kinh nghiệm. 43 | 44 | ### Kết luận (1 đoạn) 45 | - **Tóm lược**: Ôn lại những điểm chính về pattern. 46 | - **Hướng dẫn**: Đưa ra lời khuyên về khi nào nên sử dụng pattern này và khi nào nên cân nhắc đến các lựa chọn khác. 47 | 48 | ### Phụ lục (nếu cần) 49 | - **Tham khảo**: Liệt kê nguồn, đọc thêm, hoặc ví dụ trong các dự án mã nguồn mở. 50 | - **Câu hỏi thường gặp**: Bao gồm một phần để trả lời các câu hỏi thường gặp nếu cần thiết. 51 | 52 | ### Đồ họa và Phương tiện Trực quan 53 | - Sử dụng sơ đồ nơi cần thiết để minh họa cấu trúc và luồng của pattern. 54 | - Bao gồm đoạn code cho sự rõ ràng và áp dụng thực tế. 55 | - Bảng hoặc bullet point có thể hữu ích cho việc so sánh hoặc tóm tắt thông tin. 56 | 57 | ### Chiều dài và Chi tiết 58 | - Mỗi phần nên được viết ngắn gọn nhưng đầy đủ thông tin, tránh sử dụng ngôn ngữ kỹ thuật quá mức nếu có thể. 59 | - Phần giới thiệu và kết luận nên ngắn gọn, cung cấp một mở đầu và tóm tắt rõ ràng. 60 | - Phần lớn nội dung nên ở mục "Giải pháp", "Triển khai", và "Ví dụ", cung cấp giá trị và hướng dẫn thực tiễn nhất cho độc giả. 61 | 62 | ### Ngôn ngữ và Giọng điệu 63 | - Duy trì giọng điệu chuyên nghiệp nhưng dễ tiếp cận. 64 | - Sử dụng ngôn ngữ chủ động và trực tiếp để giữ sự tập trung của độc giả. 65 | - Tránh sử dụng thuật ngữ chuyên ngành và giải thích các thuật ngữ kỹ thuật khi chúng được sử dụng lần đầu tiên. 66 | 67 | Chiều dài tổng thể của bài viết nên cân bằng giữa tính toàn diện và khả năng đọc, mục tiêu khoảng 1500-3000 từ, tùy thuộc vào độ phức tạp của pattern. Nhớ rằng, mục tiêu không chỉ là thông tin mà còn là giáo dục và truyền cảm hứng cho các nhà phát triển để áp dụng hiệu quả pattern trong công việc của họ. -------------------------------------------------------------------------------- /docs/diagrams/Adapter.drawio: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /docs/diagrams/Composite.drawio: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /docs/diagrams/Singleton.drawio: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/images/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/.DS_Store -------------------------------------------------------------------------------- /docs/images/Adapter/Adapter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Adapter/Adapter.jpg -------------------------------------------------------------------------------- /docs/images/Adapter/Adapter2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Adapter/Adapter2.jpg -------------------------------------------------------------------------------- /docs/images/Adapter/Result.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Adapter/Result.PNG -------------------------------------------------------------------------------- /docs/images/Adapter/Solution.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Adapter/Solution.jpg -------------------------------------------------------------------------------- /docs/images/Adapter/pin3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Adapter/pin3.jpg -------------------------------------------------------------------------------- /docs/images/Adapter/problem.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Adapter/problem.jpg -------------------------------------------------------------------------------- /docs/images/Bridge/Problem Diagram-Page-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Bridge/Problem Diagram-Page-2.png -------------------------------------------------------------------------------- /docs/images/Bridge/Solution Diagram-Page-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Bridge/Solution Diagram-Page-3.png -------------------------------------------------------------------------------- /docs/images/Bridge/Struct Diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Bridge/Struct Diagram.png -------------------------------------------------------------------------------- /docs/images/Bridge/Untitled Diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Bridge/Untitled Diagram.png -------------------------------------------------------------------------------- /docs/images/Chain Of Responsibility/problem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Chain Of Responsibility/problem.png -------------------------------------------------------------------------------- /docs/images/Chain Of Responsibility/problem2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Chain Of Responsibility/problem2.png -------------------------------------------------------------------------------- /docs/images/Chain Of Responsibility/solution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Chain Of Responsibility/solution.png -------------------------------------------------------------------------------- /docs/images/Chain Of Responsibility/struct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Chain Of Responsibility/struct.png -------------------------------------------------------------------------------- /docs/images/Chain Of Responsibility/vidu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Chain Of Responsibility/vidu.png -------------------------------------------------------------------------------- /docs/images/Command/problem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Command/problem.png -------------------------------------------------------------------------------- /docs/images/Command/solution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Command/solution.png -------------------------------------------------------------------------------- /docs/images/Command/solution2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Command/solution2.png -------------------------------------------------------------------------------- /docs/images/Command/struct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Command/struct.png -------------------------------------------------------------------------------- /docs/images/Command/vidu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Command/vidu.png -------------------------------------------------------------------------------- /docs/images/Composite/problem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Composite/problem.png -------------------------------------------------------------------------------- /docs/images/Composite/struct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Composite/struct.png -------------------------------------------------------------------------------- /docs/images/Composite/vidu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Composite/vidu.png -------------------------------------------------------------------------------- /docs/images/Decorator/Problem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Decorator/Problem.png -------------------------------------------------------------------------------- /docs/images/Decorator/Problem2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Decorator/Problem2.png -------------------------------------------------------------------------------- /docs/images/Decorator/Solution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Decorator/Solution.png -------------------------------------------------------------------------------- /docs/images/Decorator/Vidu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Decorator/Vidu.png -------------------------------------------------------------------------------- /docs/images/Decorator/struct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Decorator/struct.png -------------------------------------------------------------------------------- /docs/images/Facade/Struct Diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Facade/Struct Diagram.png -------------------------------------------------------------------------------- /docs/images/Facade/Vidu Diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Facade/Vidu Diagram.png -------------------------------------------------------------------------------- /docs/images/Iterator/Vidu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Iterator/Vidu.png -------------------------------------------------------------------------------- /docs/images/Iterator/solution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Iterator/solution.png -------------------------------------------------------------------------------- /docs/images/Iterator/struct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Iterator/struct.png -------------------------------------------------------------------------------- /docs/images/OpenBookImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/OpenBookImage.png -------------------------------------------------------------------------------- /docs/images/Proxy/Vidu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Proxy/Vidu.png -------------------------------------------------------------------------------- /docs/images/Proxy/problem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Proxy/problem.png -------------------------------------------------------------------------------- /docs/images/Proxy/solution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Proxy/solution.png -------------------------------------------------------------------------------- /docs/images/Proxy/struct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Proxy/struct.png -------------------------------------------------------------------------------- /docs/images/Singleton/Singleton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Singleton/Singleton.png -------------------------------------------------------------------------------- /docs/images/Singleton/Singleton1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Singleton/Singleton1.png -------------------------------------------------------------------------------- /docs/images/Singleton/Singleton2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/Singleton/Singleton2.png -------------------------------------------------------------------------------- /docs/images/bmc_qr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/docs/images/bmc_qr.png -------------------------------------------------------------------------------- /src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/.DS_Store -------------------------------------------------------------------------------- /src/Behavioral Patterns/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/Behavioral Patterns/.DS_Store -------------------------------------------------------------------------------- /src/Behavioral Patterns/Chain Of Responsibility/Demo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/Behavioral Patterns/Chain Of Responsibility/Demo.class -------------------------------------------------------------------------------- /src/Behavioral Patterns/Chain Of Responsibility/RawDataTest.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/Behavioral Patterns/Chain Of Responsibility/RawDataTest.class -------------------------------------------------------------------------------- /src/Behavioral Patterns/Chain Of Responsibility/RoleTest.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/Behavioral Patterns/Chain Of Responsibility/RoleTest.class -------------------------------------------------------------------------------- /src/Behavioral Patterns/Chain Of Responsibility/Server.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/Behavioral Patterns/Chain Of Responsibility/Server.class -------------------------------------------------------------------------------- /src/Behavioral Patterns/Chain Of Responsibility/Test.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/Behavioral Patterns/Chain Of Responsibility/Test.class -------------------------------------------------------------------------------- /src/Behavioral Patterns/Chain Of Responsibility/UserExistsTest.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/Behavioral Patterns/Chain Of Responsibility/UserExistsTest.class -------------------------------------------------------------------------------- /src/Behavioral Patterns/Command/Account.kt: -------------------------------------------------------------------------------- 1 | class Account { 2 | var name : String 3 | 4 | constructor(name: String) { 5 | this.name = name 6 | } 7 | 8 | fun open() { 9 | println("Account $name Opened") 10 | } 11 | 12 | fun close() { 13 | println("Account $name Closed") 14 | } 15 | 16 | } -------------------------------------------------------------------------------- /src/Behavioral Patterns/Command/BankApp.kt: -------------------------------------------------------------------------------- 1 | class BankApp { 2 | private var openAccount: Command? = null 3 | private var closeAccount: Command? = null 4 | 5 | constructor(openAccount: Command?, closeAccount: Command?) { 6 | this.openAccount = openAccount 7 | this.closeAccount = closeAccount 8 | } 9 | 10 | 11 | fun clickOpenAccount() { 12 | println("User click open an account") 13 | openAccount!!.execute() 14 | } 15 | 16 | fun clickCloseAccount() { 17 | println("User click close an account") 18 | closeAccount!!.execute() 19 | } 20 | } -------------------------------------------------------------------------------- /src/Behavioral Patterns/Command/CloseAccount.kt: -------------------------------------------------------------------------------- 1 | class CloseAccount : Command { 2 | var account: Account 3 | 4 | constructor(account: Account) { 5 | this.account = account 6 | } 7 | 8 | 9 | override fun execute() { 10 | account.close() 11 | } 12 | } -------------------------------------------------------------------------------- /src/Behavioral Patterns/Command/Command.kt: -------------------------------------------------------------------------------- 1 | interface Command { 2 | fun execute() 3 | } -------------------------------------------------------------------------------- /src/Behavioral Patterns/Command/OpenAccount.kt: -------------------------------------------------------------------------------- 1 | class OpenAccount : Command{ 2 | var account: Account 3 | 4 | constructor(account: Account) { 5 | this.account = account 6 | } 7 | 8 | override fun execute() { 9 | account.open() 10 | } 11 | } -------------------------------------------------------------------------------- /src/Behavioral Patterns/Command/main.kt: -------------------------------------------------------------------------------- 1 | fun main(args: Array) { 2 | var account : Account = Account("NickSeven") 3 | 4 | var openAccount : Command = OpenAccount(account) 5 | 6 | var closeAccount : Command = CloseAccount(account) 7 | 8 | var bankApp : BankApp = BankApp(openAccount,closeAccount) 9 | 10 | bankApp.clickOpenAccount() 11 | 12 | bankApp.clickCloseAccount() 13 | } -------------------------------------------------------------------------------- /src/Behavioral Patterns/Iterator/Item.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/Behavioral Patterns/Iterator/Item.class -------------------------------------------------------------------------------- /src/Behavioral Patterns/Iterator/ItemIterator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/Behavioral Patterns/Iterator/ItemIterator.class -------------------------------------------------------------------------------- /src/Behavioral Patterns/Iterator/IterableCollection.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/Behavioral Patterns/Iterator/IterableCollection.class -------------------------------------------------------------------------------- /src/Behavioral Patterns/Iterator/MenuCollection.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/Behavioral Patterns/Iterator/MenuCollection.class -------------------------------------------------------------------------------- /src/Behavioral Patterns/Iterator/demo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/Behavioral Patterns/Iterator/demo.class -------------------------------------------------------------------------------- /src/structural patterns/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/structural patterns/.DS_Store -------------------------------------------------------------------------------- /src/structural patterns/Adapter/AdapterElectric.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/structural patterns/Adapter/AdapterElectric.class -------------------------------------------------------------------------------- /src/structural patterns/Adapter/Led.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/structural patterns/Adapter/Led.class -------------------------------------------------------------------------------- /src/structural patterns/Adapter/LedInterFace.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/structural patterns/Adapter/LedInterFace.class -------------------------------------------------------------------------------- /src/structural patterns/Adapter/VietNamPower.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/structural patterns/Adapter/VietNamPower.class -------------------------------------------------------------------------------- /src/structural patterns/Bridge/Account.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/structural patterns/Bridge/Account.class -------------------------------------------------------------------------------- /src/structural patterns/Bridge/Bank.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/structural patterns/Bridge/Bank.class -------------------------------------------------------------------------------- /src/structural patterns/Bridge/CheckingAccount.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/structural patterns/Bridge/CheckingAccount.class -------------------------------------------------------------------------------- /src/structural patterns/Bridge/MMBank.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/structural patterns/Bridge/MMBank.class -------------------------------------------------------------------------------- /src/structural patterns/Bridge/TPBank.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/structural patterns/Bridge/TPBank.class -------------------------------------------------------------------------------- /src/structural patterns/Bridge/TutorialAccount.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/structural patterns/Bridge/TutorialAccount.class -------------------------------------------------------------------------------- /src/structural patterns/Bridge/demo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/structural patterns/Bridge/demo.class -------------------------------------------------------------------------------- /src/structural patterns/Composite/FileComponent.kt: -------------------------------------------------------------------------------- 1 | interface FileComponent { 2 | fun showProperty() 3 | fun size() : Long 4 | } -------------------------------------------------------------------------------- /src/structural patterns/Composite/FileLeaf.kt: -------------------------------------------------------------------------------- 1 | class FileLeaf : FileComponent { 2 | 3 | private var name:String 4 | private var size:Long 5 | 6 | constructor(name: String, size: Long) { 7 | this.name = name 8 | this.size = size 9 | } 10 | 11 | 12 | override fun showProperty() { 13 | System.out.println(this.name) 14 | } 15 | 16 | override fun size(): Long { 17 | return size; 18 | } 19 | } -------------------------------------------------------------------------------- /src/structural patterns/Composite/FolderComposite.kt: -------------------------------------------------------------------------------- 1 | class FolderComposite : FileComponent{ 2 | 3 | private var files: List 4 | 5 | constructor(files: List) { 6 | this.files = files 7 | } 8 | 9 | override fun showProperty() { 10 | for (file in this.files) 11 | { 12 | file.showProperty() 13 | } 14 | 15 | } 16 | 17 | override fun size(): Long { 18 | var total : Long = 0 19 | for (file in this.files) { 20 | total += file.size() 21 | } 22 | return total 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /src/structural patterns/Composite/main.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | fun main(args: Array) { 3 | val file1: FileComponent = FileLeaf("file 1", 10) 4 | val file2: FileComponent = FileLeaf("file 2", 5) 5 | val file3: FileComponent = FileLeaf("file 3", 12) 6 | 7 | val files = Arrays.asList(file1, file2, file3) 8 | val folder: FileComponent = FolderComposite(files) 9 | 10 | folder.showProperty() 11 | println("Total Size: " + folder.size()) 12 | } -------------------------------------------------------------------------------- /src/structural patterns/Decorator/Notifier.kt: -------------------------------------------------------------------------------- 1 | interface Notifier { 2 | fun send(message : String) 3 | } -------------------------------------------------------------------------------- /src/structural patterns/Decorator/NotifierBaseDecorator.kt: -------------------------------------------------------------------------------- 1 | abstract class NotifierBaseDecorator : Notifier { 2 | 3 | var notifier : Notifier 4 | 5 | constructor(notifier: Notifier) { 6 | this.notifier = notifier 7 | } 8 | 9 | 10 | override fun send(message: String) { 11 | notifier.send(message) 12 | } 13 | } -------------------------------------------------------------------------------- /src/structural patterns/Decorator/NotifierConcrete.kt: -------------------------------------------------------------------------------- 1 | class NotifierConcrete : Notifier { 2 | 3 | override fun send(message: String) { 4 | println(message) 5 | } 6 | 7 | } -------------------------------------------------------------------------------- /src/structural patterns/Decorator/Notifier_FB.kt: -------------------------------------------------------------------------------- 1 | class Notifier_FB : NotifierBaseDecorator { 2 | 3 | constructor(notifier: Notifier) : super(notifier) 4 | 5 | override fun send(message: String) { 6 | System.out.println("Thông báo từ Facebook") 7 | super.send(message) 8 | 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /src/structural patterns/Decorator/Notifier_SMS.kt: -------------------------------------------------------------------------------- 1 | class Notifier_SMS : NotifierBaseDecorator { 2 | 3 | constructor(notifier: Notifier) : super(notifier) 4 | 5 | override fun send(message: String) { 6 | System.out.println("Thông báo qua SMS") 7 | super.send(message) 8 | } 9 | } -------------------------------------------------------------------------------- /src/structural patterns/Decorator/Notifier_Slack.kt: -------------------------------------------------------------------------------- 1 | class Notifier_Slack : NotifierBaseDecorator { 2 | 3 | constructor(notifier: Notifier) : super(notifier) 4 | 5 | override fun send(message: String) { 6 | System.out.println("Thông báo từ Slack") 7 | super.send(message) 8 | } 9 | } -------------------------------------------------------------------------------- /src/structural patterns/Decorator/main.kt: -------------------------------------------------------------------------------- 1 | fun main(args: Array) { 2 | var message : String = "Cháy nhà rồi!" 3 | 4 | var facebook = Notifier_FB(NotifierConcrete()) 5 | facebook.send(message) 6 | System.out.println("------------------------------------") 7 | 8 | var slack = Notifier_Slack(NotifierConcrete()) 9 | slack.send(message) 10 | System.out.println("------------------------------------") 11 | 12 | var sms = Notifier_SMS(NotifierConcrete()) 13 | sms.send(message) 14 | System.out.println("------------------------------------") 15 | 16 | var sms_fb_slack = Notifier_SMS(Notifier_FB(Notifier_Slack(NotifierConcrete()))) 17 | sms_fb_slack.send(message) 18 | 19 | } -------------------------------------------------------------------------------- /src/structural patterns/Facede/Demo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/structural patterns/Facede/Demo.class -------------------------------------------------------------------------------- /src/structural patterns/Facede/LoginService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/structural patterns/Facede/LoginService.class -------------------------------------------------------------------------------- /src/structural patterns/Facede/NotiService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/structural patterns/Facede/NotiService.class -------------------------------------------------------------------------------- /src/structural patterns/Facede/PayService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/structural patterns/Facede/PayService.class -------------------------------------------------------------------------------- /src/structural patterns/Facede/ShipService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/structural patterns/Facede/ShipService.class -------------------------------------------------------------------------------- /src/structural patterns/Facede/ShopFacade.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nguyenphuc22/Design-Patterns/a268b77a3c0a4f284809a403187d953d62ff5b62/src/structural patterns/Facede/ShopFacade.class -------------------------------------------------------------------------------- /src/structural patterns/Proxy/ProxyVideo.kt: -------------------------------------------------------------------------------- 1 | class ProxyVideo : Video { 2 | 3 | 4 | 5 | private var realVideo : RealVideo ? = null 6 | private var url: String 7 | 8 | constructor(url: String) { 9 | this.url = url 10 | } 11 | 12 | 13 | override fun showVideo() { 14 | if (realVideo == null) { 15 | realVideo = RealVideo(this.url) 16 | } else { 17 | println("Video already exits:${this.url}") 18 | } 19 | realVideo?.showVideo() 20 | } 21 | } -------------------------------------------------------------------------------- /src/structural patterns/Proxy/RealVideo.kt: -------------------------------------------------------------------------------- 1 | class RealVideo : Video { 2 | 3 | var url : String 4 | 5 | constructor(url: String) { 6 | this.url = url 7 | println("Video loaded: ${this.url}") 8 | } 9 | 10 | 11 | override fun showVideo() { 12 | println("Video Showed: ${this.url}") 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/structural patterns/Proxy/Video.kt: -------------------------------------------------------------------------------- 1 | interface Video { 2 | fun showVideo() 3 | } -------------------------------------------------------------------------------- /src/structural patterns/Proxy/main.kt: -------------------------------------------------------------------------------- 1 | fun main(args: Array) { 2 | var proxyVideo : ProxyVideo 3 | proxyVideo = ProxyVideo("hoclaptrinh.mp4") 4 | proxyVideo.showVideo() 5 | println() 6 | proxyVideo.showVideo() 7 | } --------------------------------------------------------------------------------