Template Method Pattern – Khuôn mẫu cho tất cả

4067

Bài viết được sự cho phép của tác giả Edward Thien Hoang

Chào mọi người, hôm nay mình sẽ tiếp tục loạt bài về Design Pattern với một pattern mới: Template Method Pattern. Từ template làm chúng ta liên tưởng đến các template trong thiết kế web, khi chúng ta có 1 trang template đã có sẵn header, footer, navigation, chỉ riêng phần boby là để trống và sẽ display nội dung theo từng page. Nghĩa là chỉ có phần body là sẽ thay đổi theo từng page, còn các phần khác sẽ giống nhau cho tất cả các page. Trừ 1 số page đặc biệt mà nội dung của header, footer, navigation sẽ thay đổi. Việc làm này sẽ giúp giảm thiểu các công việc giống nhau ở nhiều nơi. Thay vì phải viết tất cả các thành phần ở mỗi page, thì bây giờ các thành phần chung sẽ được gom lại và đặt trong một template.

  Factory Pattern - Nhà máy của những đối tượng
  Giải thích Flux Pattern theo phong cách John Wick

Trong lập trình, khái niệm template cũng tương tự như vậy. Nếu các bạn đã từ sử dụng từ khóa abstract trong Java thì khả năng cao là chính các bạn cũng đang sử dụng mẫu template này đấy.

Hãy cụ thể hóa bài toán web template ở trên vào ngôn ngữ lập trình minh họa bằng Java.

Đầu tiên hãy xây dựng một lớp PageTemplate

PageTemplate.java

package behavior.templatemethod;

public abstract class PageTemplate {

protected void displayHeader() {
System.out.println("HEADER");
}

protected void displayNavigation() {
System.out.println("NAVIGATION");
}

protected void displayFooter() {
System.out.println("FOOTER");
}

/**
* Let each subclass define it own content
* @author Edward
*/
protected abstract void displayBody();

/**
* Display all content of web page
* @author Edward
*/
public void displayWebPage() {
displayHeader();
displayNavigation();
displayBody();
displayFooter();
}
}

Lớp PageTemplate đã có sẵn các phương thức để hiển thị các thành phần header, footer, navigation. Riêng phương thức displayBody sẽ là abstract method, các trang khác nhau sẽ có nội dung hiển thị khác nhau. Sau đó cùng hiển thị tất cả lên màn hình theo một thứ tự đã cho trước trong hàm displayWebPage. Bây giờ hãy tạo ra 1 số trang sử dụng template này.

DesignPatternPage.java

package behavior.templatemethod;

public class DesignPatternPage extends PageTemplate {
@Override
protected void displayBody() {
System.out.println("DESIGN PATTERN CONTENT");
}
}

Java8TutorialPage.java

package behavior.templatemethod;

public class Java8TutorialPage extends PageTemplate {
@Override
protected void displayBody() {
System.out.println("JAVA 8 TUTORIAL CONTENT");
}
}

ContactPage.java

package behavior.templatemethod;

public class ContactPage extends PageTemplate {
@Override
protected void displayBody() {
System.out.println("ABOUT CONTENT");
}

@Override
protected void displayNavigation() {
// We do NOT want to display Navigation here
// Just do nothing
}
}

Các lớp trên đều kế thừa từ lớp PageTemplate. Chúng có một yêu cầu bắt buộc là phải implement lại method displayBody để hiển thị nội dung cho từng trang. Riêng có lớp ContactPage sẽ implement lại method displayNavigation để không hiển thị gì. Viết một lớp để test tất cả:

TemplateMethodTest.java

package behavior.templatemethod;

public class TemplateMethodTest {

public static void main(String[] args) {
PageTemplate designPattern = new DesignPatternPage();
designPattern.displayWebPage();

System.out.println();

PageTemplate java8Tutorial = new Java8TutorialPage();
java8Tutorial.displayWebPage();

System.out.println();

PageTemplate contact = new ContactPage();
contact.displayWebPage();
}

}

Kết quả khi output:

HEADER
NAVIGATION
DESIGN PATTERN CONTENT
FOOTER

HEADER
NAVIGATION
JAVA 8 TUTORIAL CONTENT
FOOTER

HEADER
ABOUT CONTENT
FOOTER

Cùng xem qua Class diagram mối quan hệ giữa các class với nhau

TemplateMethod_ClassDiagram

Như ta thấy, tất cả các page sẽ đều có chung các thành phần trong template đã định nghĩa, chúng chỉ cần implement lại những thành phần mà CHỈ CÓ RIÊNG nó mới quyết định được. Vậy nguyên lý của Template Method pattern này là: Đặt tất cả những xử lý chung trong lớp cha, sau đó định nghĩa các hàm abstract và để các lớp con tự định nghĩa lấy. Việc này sẽ giảm thiểu sự trùng lặp code và dễ dàng bảo trì về sau khi mỗi lớp con cần có sự thay đổi.

Các bạn có thể tham khảo thêm các bài viết về Design Pattern trong Series về Design Pattern

Bài viết gốc được đăng tải tại edwardthienhoang.wordpress.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev