設計模式——原型模式(ProtoType)

定義

用於創建重複的對象,同時又能保證性能。它屬於創建型設計模式,它提供了一種創建對象的最佳方法。

模板

Prototype (原型)
  Product 角色負責定義用於複製現有實例來生成新實例的方法。在示例程序中,由 Product 接口扮演此角色。
  
ConcretePrototype(具體的原型)
  ConcretePrototype 角色負責實現複製現有實例並生成新實例的方法。在示例程序中,由 MessageBox 類和 UnderlinePen 類扮演此角色。

Client(使用者)
  Client 角色負責使用複製實例的方法生成新的實例。在示例程序中,由 Manager 類扮演此角色。

實例

  1. 創建一個實現了Cloneable接口的抽象類 Shape(Prototype):
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;
   }
}
  1. 定義具體的實現類(ConcretePrototype)
//Rectangle
public class Rectangle extends Shape {
 
   public Rectangle(){
     type = "Rectangle";
   }
 
   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}

//Square
public class Square extends Shape {
 
   public Square(){
     type = "Square";
   }
 
   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}

//Circle
public class Circle extends Shape {
 
   public Circle(){
     type = "Circle";
   }
 
   @Override
   public void draw() {
      System.out.println("Inside Circle::draw() method.");
   }
}
  1. 管理類(相當於Client)
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();
   }
 
   // 對每種形狀都運行數據庫查詢,並創建該形狀
   // shapeMap.put(shapeKey, shape);
   // 例如,我們要添加三種形狀
  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);
   }
}
  1. 測試程序
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());        
   }
}

輸出結果如下:

Shape : Circle
Shape : Square
Shape : Rectangle

優點

下文的適用場景其實也是它的優點

缺點

  1. 創建多個類,增加代碼閱讀複雜性(所有設計模式通病)
  2. clone方法只是淺拷貝,除五種基礎類型之外類型都只是簡單的指向引用,不會重新創建成員變量,如需實現需要自定義clone方法。
  3. 通過clone方法不會調用類的構造函數,部分場景(在構造函數中做一些初始化操作的)需要做額外的處理

適用場景

(1)對象種類繁多,無法將它們整合到一個類中時
(2)難以根據類生成實例時
生成實例的過程太過複雜,很難根據類來 生成實例,通常,在想生成一個和之前用戶通過操作所創建出來的實例完全一樣的實例的時候,我們會事先將用戶通過操作所創建出來的實例保存起來,然後在需要時通過複製來生成新的實例。
(3)想解耦框架與生成的實例時
想要讓生成實例的框架不依賴於具體的類,這時,不能指定類名來生成實例,要事先”註冊一個原型的“實例,然後通過複製該實例來生成新的實例。

其它實例:

待補充

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章