+4

Design Patterns - Prototype Pattern

Prototype pattern đề cập đến việc tạo Object trùng lặp trong khi vẫn giữ được hiệu suất trong quá trình, là một pattern thuộc nhóm Creational Patterns.
Kiểu design pattern này được tạo ra theo mô hình Creational Pattern vì Pattern này cung cấp một trong những cách tốt nhất để tạo ra một đối tượng thay vì tạo ra Object, Prototype pattern sử dụng việc cloning (copy nguyên mẫu của Object). Ví dụ, một Object sẽ được tạo ra sau khi một hoạt động cơ sở dữ liệu tốn kém. Chúng ta có thể cache Object, trả về clone của nó theo yêu cầu tiếp theo và cập nhật cơ sở dữ liệu khi nào cần và do đó giảm các cuộc gọi cơ sở dữ liệu.

A. Thực hiện:

Trước tiên , chúng ta sẽ tạo ra 1 abstract class Shape và classes extending Shape. Class ShapeCache được định nghĩa là một bước tiếp theo lưu trữ objects hình dạng trong một "Hashtable" và trả về bản sao của chúng khi được yêu cầu. PrototypPatternDemo, lớp demo của chúng ta sẽ sử dụng lớp ShapeCache để lấy một đối tượng Shape.

Step 1:

Tạo 1 abstract class implementing 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 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 concrete classes extending của class trên.

Rectangle.java

public class Rectangle extends Shape {

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

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

Square.java

public class Square extends Shape {

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

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

Circle.java

public class Circle extends Shape {

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

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

Step 3:

Tạo một lớp để có được các lớp cụ thể từ cơ sở dữ liệu và lưu trữ chúng trong một Hashtable.

ShapeCache.java

import java.util.Hashtable;

public class ShapeCache {
	
   private static Hashtable<String, Shape> shapeMap  = new Hashtable<String, Shape>();

   public static Shape getShape(String shapeId) {
      Shape cachedShape = shapeMap.get(shapeId);
      return (Shape) cachedShape.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:

PrototypePatternDemo sử dụng lớp ShapeCache để nhận các bản sao của các hình dạng được lưu giữ trong một Hashtable

PrototypePatternDemo.java

public class PrototypePatternDemo {
   public static void main(String[] args) {
      ShapeCache.loadCache();

      Shape clonedShape = (Shape) ShapeCache.getShape("1");
      System.out.println("Shape : " + clonedShape.getType());		

      Shape clonedShape2 = (Shape) ShapeCache.getShape("2");
      System.out.println("Shape : " + clonedShape2.getType());		

      Shape clonedShape3 = (Shape) ShapeCache.getShape("3");
      System.out.println("Shape : " + clonedShape3.getType());		
   }
}

Step 5

Verify the output.:

Shape : Circle
Shape : Square
Shape : Rectangle

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

  • Tránh việc tạo nhiều lớp con cho mỗi đối tượng tạo như của Abstract Factory Pattern.

  • Giảm chi phí để tạo ra một đối tượng mới theo “ chuẩn “, điều này sẽ 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à một phương thức của một class) hơn là định nghĩa một class mới. Client có thể thể hiện một tác động khác bằng cách ủy quyền cho lớp prototype. Đồng thời cách thức khởi tạo này cũng giúp cho chúng ta khai báo một "lớp mới" mà không phải lập trình gì cả. Thực tế thì việc copy một nguyên mẫu giống như việc khởi tạo một object từ một class mới. Prototype pattern giúp giảm số lớp mà hệ thống cần 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 xây dựng hệ thống từ nhiều phần và các phần con. Các phần con lại khởi tạo từ nhiều phần con khác (chia nhỏ bài toán). Prototype pattern cũng hỗ trợ điều này. Nghĩa là các phần đó có thể được khởi tạo từ việc copy một nguyên mẫu từ một "cấu trúc" khác. Miễn là các phần kết hợp đều thể hiện Clone() và được sử dụng với cấu trúc khác nhau làm nguyên mẫu.

  • Giảm việc phân lớp: Đôi khi hệ thống quá phức tạp vì có quá nhiều class, và cây thừa kế của lớp khởi tạo có quá nhiều lớp song song cùng mức. Prototype pattern rõ ràng làm giảm số lớp và sự phức tạp của cây thừa kế (class hierarchy). Link tham khảo: https://www.tutorialspoint.com/design_pattern/prototype_pattern.htm


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí