1、模式說明java
看了比較多的資料,對原型模式寫的比較複雜,我的的理解就是模型複製,根據現有的類來直接建立新的類,而不是調用類的構造函數。框架
那爲何不直接調用new方法來建立類的實例呢,主要一個緣由是若是類的構造函數比較複雜,又須要大量的類實例對象,且這些類比較相似的時候,就可使用原型模式,調用對象的克隆方法快讀獲得實例。另外一個緣由是,使用構造函數建立類時,語句MyClass myInstance = new MyClass(); 這個Java語句中,咱們使用了要建立的類的名字:MyClass,如此一來,就講MyClass類和當前語句所在的類緊密耦合在一塊兒了,並且,若是咱們還不知道要建立的類的名字,可是想先定義類的建立方式,就須要使用原型模式。ide
2、原型模式的類圖函數
3、原型模式中的角色測試
4、代碼示例this
1.Product類:spa
package com.designpattern.cn.protptypepattern.patternframework; public interface Product extends Cloneable { public abstract void use(String s); public abstract Product createClone(); }
上面的Product類很簡單,只是繼承了java.lang.Clonable接口,該接口中並無要求實現任何方法,這是一個標記接口,被該接口標記的類能夠調用Clone方法來克隆類實例。須要注意的是,Clone方法並非定義在Clonable接口中,而是定義在java.lang.Object中,另外須要提一點,Clone方法實現的是淺複製。prototype
2.Manager類:設計
package com.designpattern.cn.protptypepattern.patternframework; import java.util.HashMap; public class Manager { private HashMap showcase = new HashMap(); public void register(String name, Product product){ showcase.put(name, product); } public Product create(String protoname){ Product p = (Product) showcase.get(protoname); return p.createClone(); } }
上面的Manager類提供了register方法,將字符串和Product接口註冊保存到showcase中,如今還沒法知道Product具體類是什麼,可是能夠肯定這個具體類是實現了Product接口的,所以這個類能夠調用use方法和createClone方法建立實例的克隆。3d
接下來建立幾種不一樣的Product具體的子類,每一個子類都實現了Product接口:
3-1.MessageBox消息盒子類:
package com.designpattern.cn.protptypepattern.patterndemostrate; import com.designpattern.cn.protptypepattern.patternframework.Product; public class MessageBox implements Product { private char decochar; public MessageBox(char decochar){ this.decochar = decochar; } public void use(String s){ int length = s.getBytes().length; for(int i = 0; i < length + 4; i++){ System.out.print(decochar); } System.out.println(""); System.out.println(decochar+" "+s+" "+decochar); for(int i = 0; i < length + 4; i++){ System.out.print(decochar); } System.out.println(""); } public Product createClone(){ Product p = null; try { p = (Product) clone(); }catch (CloneNotSupportedException e){ e.printStackTrace(); } return p; } }
3-2UnderlinePen類:
package com.designpattern.cn.protptypepattern.patterndemostrate; import com.designpattern.cn.protptypepattern.patternframework.Product; public class UnderlinePen implements Product { private char ulchar; public UnderlinePen(char ulchar){ this.ulchar = ulchar; } public void use(String s){ int length = s.getBytes().length; System.out.println("\"" + s + "\""); System.out.println(" "); for(int i = 0; i < length + 4; i++){ System.out.print(ulchar); } System.out.println(""); } public Product createClone(){ Product p = null; try { p = (Product) clone(); }catch (CloneNotSupportedException e){ e.printStackTrace(); } return p; } }
從上面兩個類能夠看出,Manager類的create方法中並無出現MessageBox和UnderlinePen這些字眼,取而代之使用的是本身定義的字符串,並將這個字符串註冊到Manager類中,後續根據字符串來獲得類實例(經過原型克隆獲得)。如此一來,就將框架和具體的類名解耦開了。
4.測試類和運行結果:
原型模式在JavaScript中也有應用,後續再補充這方面的內容,能夠對比看下Java和Javascript中實現原型模式的不一樣。
---------------------2019-06-27 00:13 比較晚了,今天加班到10點回家,原型模式仍是比較重要的,這篇隨筆後續繼續補充-----------------------------
5、JavaScript中的原型模式
在《Javascript 高級程序設計》一書中,在講如何在Javascript中建立對象時,是這樣介紹原型模式的:prototype是經過調用構造函數而建立的那個對象實例的原型對象。這句話反過來講:咱們建立的每一個函數都有一個prototype屬性,它是一個指針,指向一個對象,這個對象包含了能夠由特定類型的全部實例共享的屬性和方法。總之:沒必要在構造函數中定義對象實例信息,而是將這些信息直接添加到原型對象中。
舉例說明:
上面代碼看出,當建立一個函數時(即便函數沒有包含任何內容),就會建立一個prototype屬性,該屬性指向函數的原型對象,全部的原型對象會有一個constructor屬性,該屬性是一個指針,指向prototype屬性所在的函數的指針。上面的例子:Person.prototype.constructor 指向 Person。
使用原型對象的好處是:全部原型對象的實例都共享原型的屬性和方法。換種說法,沒必要在構造函數中定義對象實例的信息,而是將這些對象信息放到原型對象中。
由此咱們能夠想:若是咱們本身建立一個對象,做爲另外一個對象的prototype屬性值,而後經過Object.create(prototype, optionalDescriptorObjects)來實現原型繼承。
繼續完善上面的代碼:
若是咱們要本身實現原型模式:
6、與原型模式相關的模式