Template (bản mẫu) được sử dụng khi chúng ta cần triển khai tính đa hình cho một tính năng chung
được áp dụng cho nhiều kiểu dữ liệu đầu vào khác nhau. Trong Template, các hình thái triển khai
cụ thể của tính năng chung sẽ có bố cục triển khai giống nhau với các giai đoạn được sắp xếp theo
cùng trình tự. Tuy nhiên, đối với mỗi kiểu dữ liệu đầu vào cụ thể thì chúng ta lại có thể viết code triển
khai chi tiết khác nhau.
Áp dụng triển khai
Ở đây chúng ta có ví dụ về một phần mềm vẽ các hình phẳng 2D với các class mô tả thực thể
hình tròn Circle
và hình tam giác Triangle
. Tính năng chung của Shape
đó là vẽ hình bằng
phương thức draw()
với dữ liệu đầu vào là chính bản thân object mô tả thực thể. Bố cục triển
khai chung của draw()
đối với một Shape
bất kỳ luôn luôn bao gồm 3 bước chính với trình tự
thực hiện là:
- Chấm các điểm tham chiếu ban đầu
drawSamplePoints()
. - Vẽ các nét viền để định hình cho
Shape
trên mặt phẳng vẽdrawOutlines()
. - Tô kín diện tích bên trong hình sau khi đã vẽ viền xong
fillArea()
.
Các class mô tả thực thể triển khai Shape
sẽ không thể ghi đè phương thức tổng quan draw()
và chắc chắn cũng không thể thay đổi trình tự các bước vẽ hình. Tuy nhiên chi tiết của các bước
vẽ sẽ được triển khai chi tiết khác nhau đối với từng kiểu hình vẽ. Ví dụ như Circle
sẽ chấm
2 điểm tham chiếu ở bước drawSamplePoints()
và Triangle
sẽ chấm 3 điểm tham chiếu.
Bước 1
Tạo abstract Shape
để thiết lập bản mẫu của phương thức draw()
với trình tự các bước vẽ hình
được sử dụng chung cho tất cả các kiểu hình vẽ. Ở đây để đảm bảo draw()
sẽ không bị override
ở các class mô tả thực thể Circle
và Triangle
thì chúng ta cần sử dụng khóa final
.
templatepattern/Shape.java
packagetemplatepattern;publicabstractclassShape{protectedString name;publicfinalvoiddraw(){drawSamplePoints();drawOutlines();fillArea();}protectedabstractvoiddrawSamplePoints();protectedabstractvoiddrawOutlines();protectedabstractvoidfillArea();}
Bước 2
Tạo các class mô tả thực thể hình tròn Circle
và hình tam giác Triangle
. Ở đây chúng ta
cũng sẽ tạo thêm một class hỗ trợ mô tả điểm Point
với 2 tọa độ (x, y)
trong mặt phẳng vẽ.
templatepattern/Point.java
packagetemplatepattern;publicclassPoint{privateint x;privateint y;publicPoint(int x,int y
){this.x = x;this.y = y;}publicintgetX(){return x;}publicintgetY(){return y;}}
templatepattern/Circle.java
packagetemplatepattern;publicclassCircleextendsShape{privatePoint center;privateint radius;publicCircle(){this.name ="hình tròn";}publicvoidsetCenter(Point p){
center = p;}publicvoidsetRadius(int r){
radius = r;}@OverrideprotectedvoiddrawSamplePoints(){System.out.println("Bước 1:");System.out.println(" Chấm điểm O sử dụng làm tâm hình tròn ở tọa độ: "+"("+ center.getX()+", "+ center.getY()+")");System.out.println(" Chấm điểm A sử dụng làm điểm bắt đầu vẽ nét viền ở tọa độ: "+"("+ center.getX()+", "+(center.getY()-radius)+")");}@OverrideprotectedvoiddrawOutlines(){System.out.println("Bước 2:");System.out.println(" Vẽ nét viền đường tròn từ điểm A xoay quanh tâm O...");}@OverrideprotectedvoidfillArea(){System.out.println("Bước 3:");System.out.println(" Tô kín diện tích bên trong đường tròn vừa vẽ...");}}
templatepattern/Triangle.java
packagetemplatepattern;publicclassTriangleextendsShape{privatePointA;privatePointB;privatePointC;publicTriangle(){this.name ="hình tam giác";}publicvoidsetA(Point p){A= p;}publicvoidsetB(Point p){B= p;}publicvoidsetC(Point p){C= p;}@OverrideprotectedvoiddrawSamplePoints(){System.out.println("Bước 1:");System.out.println(" Chấm điểm A ở tọa độ: "+"("+A.getX()+", "+A.getY()+")");System.out.println(" Chấm điểm B ở tọa độ: "+"("+B.getX()+", "+B.getY()+")");System.out.println(" Chấm điểm C ở tọa độ: "+"("+C.getX()+", "+C.getY()+")");}@OverrideprotectedvoiddrawOutlines(){System.out.println("Bước 2:");System.out.println(" Vẽ nét viền nối từ A đến B...");System.out.println(" Vẽ nét viền nối từ B đến C...");System.out.println(" Vẽ nét viền nối từ C đến A...");}@OverrideprotectedvoidfillArea(){System.out.println("Bước 3:");System.out.println(" Tô kín diện tích bên trong các đường vừa vẽ...");}}
Bước 3
Viết code main
để thử tính năng draw()
của Circle
và Triangle
.
PatternDemo.java
importtemplatepattern.Circle;importtemplatepattern.Point;importtemplatepattern.Shape;importtemplatepattern.Triangle;publicclassPatternDemo{publicstaticvoidmain(String[] args){// Tạo object mô tả hình tròn có tọa độ tâm (10, 20)// và độ dài đường kính là 100System.out.println("========== [ Vẽ một hình tròn ] ==========");Circle circle =newCircle();
circle.setCenter(newPoint(10,20));
circle.setRadius(100);
circle.draw();// Tạo object mô tả hình tam giác với 3 điểm// A (10, 20) và B (20, -30) và C (0, -20)System.out.println("========== [ Vẽ một hình tam giác ] ==========");Triangle triangle =newTriangle();
triangle.setA(newPoint(10,20));
triangle.setB(newPoint(20,-30));
triangle.setC(newPoint(0,-20));
triangle.draw();}}
Bước 4
Kiểm chứng lại kết quả được in ra ở console
.
console
==========[Vẽ một hình tròn ]==========Bước 1:Chấm điểm O sử dụng làm tâm hình tròn ở tọa độ:(10,20)Chấm điểm A sử dụng làm điểm bắt đầu vẽ nét viền ở tọa độ:(10,-80)Bước 2:Vẽ nét viền đường tròn từ điểm A xoay quanh tâm O...Bước 3:Tô kín diện tích bên trong đường tròn vừa vẽ...==========[Vẽ một hình tam giác ]==========Bước 1:Chấm điểm A ở tọa độ:(10,20)Chấm điểm B ở tọa độ:(20,-30)Chấm điểm C ở tọa độ:(0,-20)Bước 2:Vẽ nét viền nối từ A đến B...Vẽ nét viền nối từ B đến C...Vẽ nét viền nối từ C đến A...Bước 3:Tô kín diện tích bên trong các đường vừa vẽ...
Nguồn: viblo.asia