Design Pattern | Template Method Pattern
Lại là mình, trong những bài viết trước kia, chúng ta đã tìm hiểu một loạt các mẫu thiết kế thuộc Creational và Structural. Bây giờ, sẽ tìm hiểu loại nhóm cuối cùng của Desing Pattern, các mẫu này tập trung vào việc các đối tượng riêng lẻ cộng tác để đạt được hành vi chung, người ta gọi là nhóm Behavial Pattern. Bắt đầu ở đây nào.
Khi thiết kế phần mềm, điều quan trọng là nhận ra các đối tượng khác nhau của bạn phối hợp hướng đến một mục tiêu chung. Mỗi đối tượng bạn thực hiện là một phần của một giải pháp lớn hơn. Để mỗi người thực hiện công việc của mình một cách hiệu quả, nó cần phải có một mục đích đề ra. Hãy nghĩ về nó giống như mỗi người làm việc tại một công ty, nếu người của công ty không có bất kỳ một vai trò được xác định trước nào, sẽ không có cách nào để đảm bảo rằng một người đang làm một việc mang lại lợi ích cho công ty. Tình huống này giống với Behavior Pattern, nó tập trung vào các đối tượng hướng tới mục tiêu chung. Có nhiều cách mà đối tượng có thể xác định hành vi của nó là gì, để hiểu rõ hơn, hãy xem xét một ví dụ:
Bạn đã thấy hướng dẫn để nấu súp hoặc pha chế đồ uống từ bột ? Cả hai sẽ có các bước miêu tả tương tự, sẽ có một số bước giống hệt nhau.
Giả sử bạn là đầu bếp điều hành một chuỗi nhà hàng lớn về mì ống, bạn muốn các món ăn được nhất quán tại tất cả các địa điểm nhà hàng trong chuỗi, vì vây bạn cung cung cấp hướng dẫn để thực hiện mỗi món ăn. Hai món ăn phổ biến nhất là mì Spaghetti với sốt cà chua và thịt viên, mì Penne với sốt Alfredo và thịt gà. Cả hai món ăn đều yêu cầu bạn đun nước, nấu mì ống, thêm nước sốt, thêm protein, và trang trí. Một số bước này được thực hiện khác nhau tùy thuộc vào món ăn bạn làm, mỗi món ăn có một loại protein, nước sốt và trang trí khác nhau.
Bạn có thể mô hình hóa tình huống này, phương pháp làm món mì nói chung sẽ có tập cụ thể các bước có thể làm chung. Các bước đặc biệt cho món ăn, được thực hiện trong lớp con của mỗi món mì đó. Template Method Pattern xác định các bước của thuật toán nói chung, trì hoãn việc thực hiện một số bước của các lớp con, phân công trách nhiệm.
Giống như phương tiện đều có mục đích chung là đi đến đích, ở đây là xe hơi và xe máy, trên đường đi, xe hơi và xe máy đều có cách xử lý nhìn chung là giống nhau, ngoặt trái, phải, lên cầu .v.v Bạn cần nhận ra ở đây là hai lớp riêng biệt lại có chức năng giống nhau theo thứ tự các thao tác.
Hãy xem sơ đồ UML sau:
Chúng ta có superclass PastaDish với Template Method (phương thức mẫu), makeRecipe() gọi các phương thức khác cho các bước của công thức, một số bước phổ biển trên cả hai món ăn là boilWater(), cookPasta(), drainAndPalte() nên là một là phương thức bình thường của PastaDish. Tuy nhiên, một số phương thức đặc biệt chỉ có thể làm trên từng loại món ăn, vì vậy addPasta() là một phương thức trừu tượng của PastaDish, nó sẽ tùy thuộc vào lốp con của PastaDish để thêm công thức pha chế phù hợp. SpaghetiMeatballs và PenneAlfredo là hai lớp con của pastaDish, nó phải cung cấp các phương thức addPasta(), addSauce(), addProtein(), addGarnish() của riêng nó.
Như thế, PastaDish phải là một lớp abstract, bạn không thể biết trước addPasta(), addSauce(), addProtein(), addGarnish() vì nó là đặc trưng riêng của mỗi lớp con. Trong Java, từ khóa final có nghĩa là phương thức khai báo không thể bị ghi đè bởi các lớp con, điều này có nghĩa là không có lớp con món ăn cụ thể nào có thể có makeRecipe() riêng, điều này đảm bảo tính nhất quán trong món ăn và giảm code thừa.
Các phương thức như boilWater().v.v được thực hiện tương tự với mọi lớp con, vì thế, nó được implement trong superclass.
Ta có thể thấy hai subclass phải hoàn thành những gì mà superclass bắt đầu.
Phương thức này hữu ích nếu bạn có hai lớp có chức năng tương tự nhau, khi bạn nhận thấy hai lớp có thứ tự hoạt động giống nhau, bạn có thể chọn sử dụng nó, nó là một ứng dụng thực tế của khải quát hóa và kế thừa.
Cảm ơn, đây có lẽ là bài đăng nhẹ nhàng nhất trong Design Pattern đến thời điểm này rồi.
Khi thiết kế phần mềm, điều quan trọng là nhận ra các đối tượng khác nhau của bạn phối hợp hướng đến một mục tiêu chung. Mỗi đối tượng bạn thực hiện là một phần của một giải pháp lớn hơn. Để mỗi người thực hiện công việc của mình một cách hiệu quả, nó cần phải có một mục đích đề ra. Hãy nghĩ về nó giống như mỗi người làm việc tại một công ty, nếu người của công ty không có bất kỳ một vai trò được xác định trước nào, sẽ không có cách nào để đảm bảo rằng một người đang làm một việc mang lại lợi ích cho công ty. Tình huống này giống với Behavior Pattern, nó tập trung vào các đối tượng hướng tới mục tiêu chung. Có nhiều cách mà đối tượng có thể xác định hành vi của nó là gì, để hiểu rõ hơn, hãy xem xét một ví dụ:
Bạn đã thấy hướng dẫn để nấu súp hoặc pha chế đồ uống từ bột ? Cả hai sẽ có các bước miêu tả tương tự, sẽ có một số bước giống hệt nhau.
Giả sử bạn là đầu bếp điều hành một chuỗi nhà hàng lớn về mì ống, bạn muốn các món ăn được nhất quán tại tất cả các địa điểm nhà hàng trong chuỗi, vì vây bạn cung cung cấp hướng dẫn để thực hiện mỗi món ăn. Hai món ăn phổ biến nhất là mì Spaghetti với sốt cà chua và thịt viên, mì Penne với sốt Alfredo và thịt gà. Cả hai món ăn đều yêu cầu bạn đun nước, nấu mì ống, thêm nước sốt, thêm protein, và trang trí. Một số bước này được thực hiện khác nhau tùy thuộc vào món ăn bạn làm, mỗi món ăn có một loại protein, nước sốt và trang trí khác nhau.
Bạn có thể mô hình hóa tình huống này, phương pháp làm món mì nói chung sẽ có tập cụ thể các bước có thể làm chung. Các bước đặc biệt cho món ăn, được thực hiện trong lớp con của mỗi món mì đó. Template Method Pattern xác định các bước của thuật toán nói chung, trì hoãn việc thực hiện một số bước của các lớp con, phân công trách nhiệm.
Giống như phương tiện đều có mục đích chung là đi đến đích, ở đây là xe hơi và xe máy, trên đường đi, xe hơi và xe máy đều có cách xử lý nhìn chung là giống nhau, ngoặt trái, phải, lên cầu .v.v Bạn cần nhận ra ở đây là hai lớp riêng biệt lại có chức năng giống nhau theo thứ tự các thao tác.
Hãy xem sơ đồ UML sau:
Chúng ta có superclass PastaDish với Template Method (phương thức mẫu), makeRecipe() gọi các phương thức khác cho các bước của công thức, một số bước phổ biển trên cả hai món ăn là boilWater(), cookPasta(), drainAndPalte() nên là một là phương thức bình thường của PastaDish. Tuy nhiên, một số phương thức đặc biệt chỉ có thể làm trên từng loại món ăn, vì vậy addPasta() là một phương thức trừu tượng của PastaDish, nó sẽ tùy thuộc vào lốp con của PastaDish để thêm công thức pha chế phù hợp. SpaghetiMeatballs và PenneAlfredo là hai lớp con của pastaDish, nó phải cung cấp các phương thức addPasta(), addSauce(), addProtein(), addGarnish() của riêng nó.
Như thế, PastaDish phải là một lớp abstract, bạn không thể biết trước addPasta(), addSauce(), addProtein(), addGarnish() vì nó là đặc trưng riêng của mỗi lớp con. Trong Java, từ khóa final có nghĩa là phương thức khai báo không thể bị ghi đè bởi các lớp con, điều này có nghĩa là không có lớp con món ăn cụ thể nào có thể có makeRecipe() riêng, điều này đảm bảo tính nhất quán trong món ăn và giảm code thừa.
Các phương thức như boilWater().v.v được thực hiện tương tự với mọi lớp con, vì thế, nó được implement trong superclass.
Ta có thể thấy hai subclass phải hoàn thành những gì mà superclass bắt đầu.
Phương thức này hữu ích nếu bạn có hai lớp có chức năng tương tự nhau, khi bạn nhận thấy hai lớp có thứ tự hoạt động giống nhau, bạn có thể chọn sử dụng nó, nó là một ứng dụng thực tế của khải quát hóa và kế thừa.
Cảm ơn, đây có lẽ là bài đăng nhẹ nhàng nhất trong Design Pattern đến thời điểm này rồi.
Nhận xét
Đăng nhận xét