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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 | }
--------------------------------------------------------------------------------