設計模式-原型模式(06)
定義
原型(Prototype Pattern)是一個簡單的設計模式。原型模式的英文原話是:Specify the kind of objects to create using a prototypical instance,and create new objects by copying this prototype.意思是:用原型實例指定創建對象的種類,並且通過復制這些原型創建新的對象。
原型模式有三種角色:
1.客戶(Client)角色:該角色提出創建對象的請求。
2.抽象原型(Prototype):該角色是一個抽象角色,通常由一個java接口或抽象類實現,給出所有的具體原型類所需要的接口。
java中內置了克隆機制。object類具有一個clone()方法,能夠實現對對象的克隆,是一個類支持克隆只需要兩步:
1.實現Cloneable接口。
2.覆蓋Object的clone()方法,完成對象的克隆操作,通常只需要調用Object的clone()方法即可。為了使外部能夠調用此類的clone()方法,可以將訪問修飾符改為public。
/** * 抽象原型角色(Prototype) * 給出具體原型類復制所需要的接口 */ public interfacePrototype { //克隆方法 Prototype clone(); } /** * 具體原型工廠類 * */ public class ConcretePrototype implements Prototype { @Override public Prototype clone() { try { return (Prototype)super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace();return null; } } } public class Client { public void operation(Prototype example) { //得到example Prototype prototype = example.clone(); } }
原型模式的優點
1.性能優良:原型模式是對內存中二進制流的拷貝,要比直接new一個對象性能好,特別是當一個循環體內產生大量的對象時,原型模式可以更好地體現其優點。
2.逃避構造函數的約束。這既是優點也是缺點,直接在內存中拷貝對象,構造函數是不會執行的,因此減少了約束,不過這一點需要在實際應用時進行權衡考慮。
原型模式的使用場景
1.資源優化場景,類初始化時需要消化非常多的資源,這個資源包括數據、硬件資源等。
2.性能和安全要求的場景,如果通過new產生一個對象需要非常繁瑣的數據準備和訪問權限,則可以使用原型模式。
3.一個對象多個修改者的場景,一個對象需要提供給其他對象訪問,而且各個調用者可能都需要修改其值,可以考慮使用原型模式拷貝多個對象供調用者使用。
在實際項目中,原型模式很少單獨出現,一般是和工廠方法模式一起出現。原型模式通過clone()方法創建一個對象,然後由工廠方法提供給調用者。
例子
/** * 實現clone接口,實現了clone方法,是實現克隆的關鍵 */ public class Mail implements Cloneable { //收件人 private String receiver; //郵件標題 private String subject; //稱謂 private String appellation; //郵件內容 private String contxt; //尾部 private String tail; //構造函數 public Mail(String subject,String contxt) { this.subject = subject; this.contxt = contxt; } //克隆方法 public Mail clone() { Mail mail = null; try { mail=(Mail) super.clone(); System.out.println(super.toString()); //super指的是被調用的那個對象 } catch (CloneNotSupportedException e) { e.printStackTrace(); } return mail; } } /** * 調用 */ public class SendMailDemo { Map students = new LinkedHashMap(); public static void main(String[] args) { //創建一個原型mail Mail mail = new Mail("郵件標題", "郵件內容"); mail.setTail("2017-11-20"); SendMailDemo sendMailDemo = new SendMailDemo(); //獲取所有學生 Map students=sendMailDemo.getStudent(); for (Object name : students.keySet()) { //克隆郵件 Mail cloneMail = mail.clone(); cloneMail.setAppellation(name.toString()); cloneMail.setReceiver(students.get(name).toString()); sendMailDemo.sendMail(cloneMail); } } public Map getStudent(){ students.put("studentone", "[email protected]"); students.put("studenttwo", "[email protected]"); students.put("studentthree", "[email protected]"); students.put("studentfour", "[email protected]"); students.put("studentfive", "[email protected]"); students.put("studentsix", "[email protected]"); students.put("studentseven", "[email protected]"); return students; } public void sendMail(Mail mail){ System.out.println("標題:"+mail.getSubject()+"\t收件人郵箱:"+mail.getReceiver()+"\t正文:"+mail.getAppellation()+mail.getContxt()+"\t...已發送"); } }
源碼
設計模式-原型模式(06)