Gia Bao TSC

Prototype Pattern

Tiếp theo chuỗi bài về Design Pattern, chúng ta tiếp tục nghiên cứu một pattern nữa thuộc nhóm Creational Patterns. Pattern này cung cấp một trong những cách tốt nhất để tạo ra đối tượng thay vì tạo ra Object, thay vào đó nó sẽ sử dụng việc cloning để thực hiện. Và chúng ta đang nói về Prototype. Chúng ta sẽ cache Object và trả về clone của nó theo yêu cầu.

 Design Patterns  posted at February 22, 2019

A. Thực hiện

Trước tiên, chúng ta sẽ tạo ra một abstract class Shape và các class khác extends từ Shape. Tiếp theo là định nghĩa một class có tên ShapeCache để lưu trữ Shape object trong Hashtable và trả về clone của chúng khi có yêu cầu. Và cuối cùng là PrototypePatternDemo là class được sử dụng để kiểm tra kết quả. Dưới đây là UML của Prototype:

Step 1:

Tạo abstract class implement Clonable interface

Shape.java


public abstract class Shape implements Cloneable {

	private String id;
	
	protected String type;
	
	abstract void draw();
	
	public String getType() {
		return type;
	}
	
	public void setType(String type) {
		this.type = type;
	}
	
	public String getId() {
		return id;
	}
	
	public void setId(String id) {
		this.id = id;
	}
	
	public Object clone() {
		
		Object clone = null;
		
		try {
			clone = super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		
		return clone;
	}
}

Step 2:

Tạo các concrete class extend từ Shape

Rectangle.java


public class Rectangle extends Shape {

	public Rectangle() {
		type = "Rectangle";
	}

	@Override
	void draw() {
		System.out.println("Inside Rectangle::draw() method.");
	}
}

Square.java


public class Square extends Shape {

	public Square() {
		type = "Square";
	}

	@Override
	void draw() {
		System.out.println("Inside Square::draw() method.");
	}
}

Circle.java


public class Circle extends Shape {

	public Circle() {
		type = "Circle";
	}

	@Override
	void draw() {
		System.out.println("Inside Circle::draw() method.");
	}
}

Step 3:

Tạo class để cache, lưu giữ object và trả về clone khi có yêu cầu

ShapeCache.java


public class ShapeCache {

	private static Hashtable shapeMap = new Hashtable<>();
	
	public static Shape getShape(String shapeId) {
		
		Shape cacheShape = shapeMap.get(shapeId);
		
		return (Shape) cacheShape.clone();
	}

	// for each Shape run database query and create shape
	// shapeMap.put(shapeKey, shape)
	// for example, we are adding three shapes
	public static void loadCache() {
		
		Circle circle = new Circle();
		circle.setId("1");
		shapeMap.put(circle.getId(), circle);
		
		Square square = new Square();
		square.setId("2");
		shapeMap.put(square.getId(), square);
		
		Rectangle rectangle = new Rectangle();
		rectangle.setId("3");
		shapeMap.put(rectangle.getId(), rectangle);
	}
}

Step 4:

Cuối cùng là chúng ta tạo class để kiểm tra sự hoạt động của Prototype pattern đã được sử dụng

PrototypePatternDemo.java


public class PrototypePatternDemo {

	public static void main(String[] args) {
		
		ShapeCache.loadCache();
		
		Shape clonedShape = ShapeCache.getShape("1");
		System.out.println("Shape: " + clonedShape.getType());
		
		Shape clonedShape2 = ShapeCache.getShape("2");
		System.out.println("Shape: " + clonedShape2.getType());
		
		Shape clonedShape3 = ShapeCache.getShape("3");
		System.out.println("Shape: " + clonedShape3.getType());
	}
}

Step 5:

Kết quả từ việc chạy chương trình

Shape: Circle
Shape: Square
Shape: Rectangle

B. Một số ưu điểm

  • Tránh việc tạo nhiều class con cho mỗi đối tượng.
  • Giảm chi phí để tạo một đối tượng theo mẫu, và làm tăng hiệu suất so với việc sử dụng từ khóa new để tạo đối tượng mới.
  • Khởi tạo object mới bằng cách thay đổi một vài thuộc tính của object (các object có ít điểm khác biệt nhau). Một hệ thống linh động sẽ để cho chúng ta tự định nghĩa một hành động nào đó thông qua sự kết hợp với một object (nghĩa là phương thức của một class) hơn là định nghĩa ra một class mới. Điều này làm giảm số lượng class mà hệ thống cần sử dụng.
  • Khởi tạo object mới bằng cách thay đổi cấu trúc: Rất nhiều ứng dụng được xây dựng dựa trên nhiều thành phần và các class con. Các phần con lại được khởi tạo từ nhiều thành phần con khác. Prototype pattern cũng hỗ trợ điều này. Nghĩa là các phần đó có thể được khởi tạo bằng cách copy một nguyên mẫu từ một cấu trúc khac. Miễn là các phần kết hợp đều thể hiện Clone() và được sử dụng với các cấu trúc khác nhau làm nguyên mẫu.
  • Giảm việc phân lớp, điều này giúp cho cây thừa kế sẽ đơn giản hơn rất nhiều (class hierarchy).

Tham khảo

Source Code

Gia Bao TSC