Java設(shè)計(jì)模式(四)之原型模式

一、概述

原型模式(Prototype Pattern)用于創(chuàng)建重復(fù)的對(duì)象墙杯,同時(shí)又能保證性能配并。它屬于創(chuàng)建型設(shè)計(jì)模式,它提供了一種創(chuàng)建對(duì)象的最佳方法高镐。
這種模式是實(shí)現(xiàn)了一個(gè)原型接口溉旋,該接口用于創(chuàng)建當(dāng)前對(duì)象的克隆。當(dāng)直接創(chuàng)建對(duì)象的代價(jià)比較大時(shí)嫉髓,則采用這種模式观腊。例如,一個(gè)對(duì)象需要在一個(gè)高代價(jià)的數(shù)據(jù)庫操作之后被創(chuàng)建算行。我們可以緩存該對(duì)象恕沫,在下一個(gè)請(qǐng)求時(shí)返回它的克隆,在需要的時(shí)候更新數(shù)據(jù)庫纱意,以此來減少數(shù)據(jù)庫調(diào)用婶溯。

二、介紹

意圖:用原型實(shí)例指定創(chuàng)建對(duì)象的種類偷霉,并且通過拷貝這些原型創(chuàng)建新的對(duì)象迄委。
主要解決:在運(yùn)行期建立和刪除模型。
何時(shí)使用

  1. 當(dāng)一個(gè)系統(tǒng)應(yīng)該獨(dú)立于它的產(chǎn)品創(chuàng)建类少,構(gòu)成和表示時(shí)叙身。
  2. 當(dāng)要實(shí)例化的類是在運(yùn)行時(shí)指定時(shí),例如硫狞,通過動(dòng)態(tài)裝載信轿。
  3. 為了避免一個(gè)與產(chǎn)品類層次平行的工廠類層次時(shí)晃痴。
  4. 當(dāng)一個(gè)類的實(shí)例只能有幾個(gè)不同狀態(tài)組合中的一種時(shí)。創(chuàng)建相應(yīng)數(shù)目的原型并克隆它們可能比每次用何時(shí)的狀態(tài)手工實(shí)例化該類更方便一些财忽。

如何解決:利用已有的一個(gè)原型對(duì)象倘核,快速地生成和原型對(duì)象一樣的實(shí)例。

  1. 實(shí)現(xiàn)克隆操作即彪,繼承Cloneable紧唱,重寫clone()方法。
  2. 原型模式同樣用于隔離類對(duì)象的使用者和具體類型(易變類)之間的耦合關(guān)系隶校,它同樣要求這些“易變類”擁有穩(wěn)定的接口漏益。

應(yīng)用實(shí)例細(xì)胞分裂;Object的clone()方法深胳。
優(yōu)點(diǎn)性能提高绰疤;逃避構(gòu)造函數(shù)的約束。
缺點(diǎn)

  1. 配備克隆方法需要對(duì)類的功能進(jìn)行通盤考慮舞终,這對(duì)于全新的類不是很難峦睡,但對(duì)于已有的類不一定容易,特別當(dāng)一個(gè)類引用不支持串行化的間接對(duì)象权埠,或者引用含有循環(huán)結(jié)構(gòu)的時(shí)候榨了。
  2. 必須實(shí)現(xiàn)Cloneable接口。

使用場景

  1. 資源優(yōu)化場景攘蔽。
  2. 類初始化需要消耗非常多的資源龙屉,這個(gè)資源包括數(shù)據(jù)、硬件資源等满俗。
  3. 性能和安全要求的場景转捕。
  4. 通過new產(chǎn)生一個(gè)對(duì)象需要非常繁瑣的數(shù)據(jù)準(zhǔn)備或訪問權(quán)限,則可以使用原型模式唆垃。
  5. 一個(gè)對(duì)象多個(gè)修改者的場景五芝。
  6. 一個(gè)對(duì)象需要提供給其他對(duì)象訪問,而且各個(gè)調(diào)用者可能都需要修改其值時(shí)辕万,可以考慮使用原型模式拷貝多個(gè)對(duì)象供調(diào)用者使用枢步。
  7. 在實(shí)際項(xiàng)目中,原型模式很少單獨(dú)出現(xiàn)渐尿,一般是和工廠模式一起出現(xiàn)醉途,通過clone方法創(chuàng)建一個(gè)對(duì)象,然后由工廠方法提供給調(diào)用者砖茸。

注意事項(xiàng):與通過對(duì)一個(gè)類進(jìn)行實(shí)例化來構(gòu)造新對(duì)象不同的是隘擎,原型模式是通過拷貝一個(gè)現(xiàn)有對(duì)象生成新對(duì)象的。淺拷貝實(shí)現(xiàn)Cloneable凉夯,重寫货葬,深拷貝是通過實(shí)現(xiàn)Serializable讀取二進(jìn)制流采幌。

三、實(shí)現(xiàn)

我們將創(chuàng)建一個(gè)抽象類 Shape 和擴(kuò)展了 Shape 類的實(shí)體類震桶。下一步是定義類ShapeCache休傍,該類把shape對(duì)象存儲(chǔ)在一個(gè)Hashtable中,并在請(qǐng)求的時(shí)候返回他們的克隆尼夺。具體UML圖如下:

  • 步驟1
    創(chuàng)建一個(gè)實(shí)現(xiàn)了Cloneable接口的抽象類 Shape:
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;
   }
}
  • 步驟2
    創(chuàng)建擴(kuò)展了上面抽象類的實(shí)體類:

//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.");
   }
}
  • 步驟3
    創(chuàng)建一個(gè)類,從數(shù)據(jù)庫獲取實(shí)體類炒瘸,并把它們存儲(chǔ)在一個(gè)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();
   }
 
   // 對(duì)每種形狀都運(yùn)行數(shù)據(jù)庫查詢,并創(chuàng)建該形狀
   // 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);
   }
}
  • 步驟4
    測試類:
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());        
   }
}

輸出結(jié)果:

Shape : Circle
Shape : Square
Shape : Rectangle

參考文章:原型模式 | 菜鳥教程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末拐邪,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子隘截,更是在濱河造成了極大的恐慌扎阶,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件婶芭,死亡現(xiàn)場離奇詭異东臀,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)犀农,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門惰赋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人呵哨,你說我怎么就攤上這事赁濒。” “怎么了孟害?”我有些...
    開封第一講書人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵拒炎,是天一觀的道長。 經(jīng)常有香客問我挨务,道長击你,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任谎柄,我火速辦了婚禮果漾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘谷誓。我一直安慰自己绒障,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開白布捍歪。 她就那樣靜靜地躺著户辱,像睡著了一般鸵钝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上庐镐,一...
    開封第一講書人閱讀 49,785評(píng)論 1 290
  • 那天恩商,我揣著相機(jī)與錄音,去河邊找鬼必逆。 笑死怠堪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的名眉。 我是一名探鬼主播粟矿,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼损拢!你這毒婦竟也來了陌粹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤福压,失蹤者是張志新(化名)和其女友劉穎掏秩,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體荆姆,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蒙幻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了胆筒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杆煞。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖腐泻,靈堂內(nèi)的尸體忽然破棺而出决乎,到底是詐尸還是另有隱情,我是刑警寧澤派桩,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布构诚,位于F島的核電站,受9級(jí)特大地震影響铆惑,放射性物質(zhì)發(fā)生泄漏范嘱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一员魏、第九天 我趴在偏房一處隱蔽的房頂上張望丑蛤。 院中可真熱鬧,春花似錦撕阎、人聲如沸受裹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽棉饶。三九已至厦章,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間照藻,已是汗流浹背袜啃。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留幸缕,地道東北人群发。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像发乔,于是被迫代替她去往敵國和親熟妓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348