原型模式主要用於對象的複製,它的核心是就是類圖中的原型類Prototype。Prototype類須要具有如下兩個條件:html
/** * 原型模式 */ public class Prototype implements Cloneable { private String name; @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } public String getName() { return name; } public void setName(String name) { this.name = name; } } /** * 測試與應用類 */ public class Test { public static void main(String[] args) throws CloneNotSupportedException { Prototype prototype = new Prototype(); prototype.setName("K.O"); List<String> names = new ArrayList<>(); names.add("K.O"); prototype.setNames(names); for (int i = 0; i < 5; i ++) { Prototype p = (Prototype) prototype.clone(); p.setName("sigma"); p.getNames().add("sigma"); System.out.println(p.toString()); System.out.println(p.getName()); System.out.println(p.getNames().size()); } System.out.println(prototype.toString()); System.out.println(prototype.getName()); System.out.println(prototype.getNames().size()); } }
org.ko.prototype.basic.Prototype@1540e19d sigma 2 org.ko.prototype.basic.Prototype@677327b6 sigma 3 org.ko.prototype.basic.Prototype@14ae5a5 sigma 4 org.ko.prototype.basic.Prototype@7f31245a sigma 5 org.ko.prototype.basic.Prototype@6d6f6e28 sigma 6 org.ko.prototype.basic.Prototype@135fbaa4 K.O 6
能夠看出,輸出結果中對象的地址不一樣(是從新建立的)java
原型模式的各個元素,原型模式比較簡單,元素比較少git
/** * Mail實現類 * 實現 Cloneable 接口 * 重寫 Object.clone() 方法 */ public class Mail implements Cloneable { private String name; private String emailAddress; private String content; public Mail () { System.out.println("Mail Class Constructor!"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmailAddress() { return emailAddress; } public void setEmailAddress(String emailAddress) { this.emailAddress = emailAddress; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } @Override public String toString() { return "Mail{" + "name='" + name + '\'' + ", emailAddress='" + emailAddress + '\'' + ", content='" + content + '\'' + '}' + super.toString(); } @Override protected Object clone() throws CloneNotSupportedException { System.out.println("clone mail object!"); return super.clone(); } } /** * Mail工具類 */ public class MailUtil { public static void sendMail (Mail mail) { String outputContent = "向{0}同窗, 郵件地址:{1},郵件內容:{2}, 發送郵件成功!"; System.out.println(MessageFormat.format( outputContent, mail.getName(), mail.getEmailAddress(), mail.getContent()) ); } public static void saveOriginMailRecord (Mail mail) { System.out.println("存儲originMail記錄, originMail: " + mail.getContent()); } }
/** * 測試與應用 */ public class Test { public static void main(String[] args) throws CloneNotSupportedException { Mail mail = new Mail(); mail.setContent("初始化模板"); System.out.println("初始化mail: " + mail.toString()); for (int i = 0; i < 10; i++) { Mail mailTemp = (Mail) mail.clone(); //並無調用Mail構造器 mailTemp.setName("K.O_" + i); mailTemp.setEmailAddress("ko.shen_" + i + "@hotmail.com"); mailTemp.setContent("恭喜您中獎了。"); MailUtil.sendMail(mailTemp); System.out.println("克隆的mailTemp: " + mailTemp.toString()); } MailUtil.saveOriginMailRecord(mail); } }
Mail Class Constructor! 初始化mail: Mail{name='null', emailAddress='null', content='初始化模板'}org.ko.prototype.v2.Mail@1540e19d clone mail object! 向K.O_0同窗, 郵件地址:ko.shen_0@hotmail.com,郵件內容:恭喜您中獎了。, 發送郵件成功! 克隆的mailTemp: Mail{name='K.O_0', emailAddress='ko.shen_0@hotmail.com', content='恭喜您中獎了。'}org.ko.prototype.v2.Mail@677327b6 clone mail object! 向K.O_1同窗, 郵件地址:ko.shen_1@hotmail.com,郵件內容:恭喜您中獎了。, 發送郵件成功! 克隆的mailTemp: Mail{name='K.O_1', emailAddress='ko.shen_1@hotmail.com', content='恭喜您中獎了。'}org.ko.prototype.v2.Mail@14ae5a5 clone mail object! 向K.O_2同窗, 郵件地址:ko.shen_2@hotmail.com,郵件內容:恭喜您中獎了。, 發送郵件成功! 克隆的mailTemp: Mail{name='K.O_2', emailAddress='ko.shen_2@hotmail.com', content='恭喜您中獎了。'}org.ko.prototype.v2.Mail@7f31245a clone mail object! 向K.O_3同窗, 郵件地址:ko.shen_3@hotmail.com,郵件內容:恭喜您中獎了。, 發送郵件成功! 克隆的mailTemp: Mail{name='K.O_3', emailAddress='ko.shen_3@hotmail.com', content='恭喜您中獎了。'}org.ko.prototype.v2.Mail@6d6f6e28 clone mail object! 向K.O_4同窗, 郵件地址:ko.shen_4@hotmail.com,郵件內容:恭喜您中獎了。, 發送郵件成功! 克隆的mailTemp: Mail{name='K.O_4', emailAddress='ko.shen_4@hotmail.com', content='恭喜您中獎了。'}org.ko.prototype.v2.Mail@135fbaa4 clone mail object! 向K.O_5同窗, 郵件地址:ko.shen_5@hotmail.com,郵件內容:恭喜您中獎了。, 發送郵件成功! 克隆的mailTemp: Mail{name='K.O_5', emailAddress='ko.shen_5@hotmail.com', content='恭喜您中獎了。'}org.ko.prototype.v2.Mail@45ee12a7 clone mail object! 向K.O_6同窗, 郵件地址:ko.shen_6@hotmail.com,郵件內容:恭喜您中獎了。, 發送郵件成功! 克隆的mailTemp: Mail{name='K.O_6', emailAddress='ko.shen_6@hotmail.com', content='恭喜您中獎了。'}org.ko.prototype.v2.Mail@330bedb4 clone mail object! 向K.O_7同窗, 郵件地址:ko.shen_7@hotmail.com,郵件內容:恭喜您中獎了。, 發送郵件成功! 克隆的mailTemp: Mail{name='K.O_7', emailAddress='ko.shen_7@hotmail.com', content='恭喜您中獎了。'}org.ko.prototype.v2.Mail@2503dbd3 clone mail object! 向K.O_8同窗, 郵件地址:ko.shen_8@hotmail.com,郵件內容:恭喜您中獎了。, 發送郵件成功! 克隆的mailTemp: Mail{name='K.O_8', emailAddress='ko.shen_8@hotmail.com', content='恭喜您中獎了。'}org.ko.prototype.v2.Mail@4b67cf4d clone mail object! 向K.O_9同窗, 郵件地址:ko.shen_9@hotmail.com,郵件內容:恭喜您中獎了。, 發送郵件成功! 克隆的mailTemp: Mail{name='K.O_9', emailAddress='ko.shen_9@hotmail.com', content='恭喜您中獎了。'}org.ko.prototype.v2.Mail@7ea987ac 存儲originMail記錄, originMail: 初始化模板
/** * 淺克隆 */ public class Pig1 implements Cloneable { private String name; private Date birthday; public Pig1(String name, Date birthday) { this.name = name; this.birthday = birthday; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() { return "Pig1{" + "name='" + name + '\'' + ", birthday=" + birthday + '}' + super.toString(); } }
public class Test1 { public static void main(String[] args) throws CloneNotSupportedException { //淺克隆, 沒辦法克隆引用對象 Date birthday = new Date(0l); Pig1 pig1 = new Pig1("佩奇", birthday); Pig1 pig2 = (Pig1) pig1.clone(); System.out.println(pig1); System.out.println(pig2); System.out.println("-------"); pig1.getBirthday().setTime(666666666666L); System.out.println(pig1); System.out.println(pig2); } }
Pig1{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}org.ko.prototype.clone.Pig1@6d6f6e28 Pig1{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}org.ko.prototype.clone.Pig1@135fbaa4 ------- Pig1{name='佩奇', birthday=Sat Feb 16 09:11:06 CST 1991}org.ko.prototype.clone.Pig1@6d6f6e28 Pig1{name='佩奇', birthday=Sat Feb 16 09:11:06 CST 1991}org.ko.prototype.clone.Pig1@135fbaa4
/** * 深克隆 */ public class Pig2 implements Cloneable { private String name; private Date birthday; public Pig2(String name, Date birthday) { this.name = name; this.birthday = birthday; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Override protected Object clone() throws CloneNotSupportedException { Pig2 pig2 = (Pig2) super.clone(); //深克隆, 要本身去作對象引用的克隆 pig2.birthday = (Date) pig2.birthday.clone(); return pig2; } @Override public String toString() { return "Pig1{" + "name='" + name + '\'' + ", birthday=" + birthday + '}' + super.toString(); } }
public class Test2 { public static void main(String[] args) throws CloneNotSupportedException { //深克隆 Date birthday = new Date(0l); Pig2 p1 = new Pig2("佩奇", birthday); Pig2 p2 = (Pig2) p1.clone(); System.out.println(p1); System.out.println(p2); System.out.println("-------"); p1.getBirthday().setTime(666666666666L); System.out.println(p1); System.out.println(p2); } }
Pig2{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}org.ko.prototype.clone.Pig2@6d6f6e28 Pig2{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}org.ko.prototype.clone.Pig2@135fbaa4 ------- Pig2{name='佩奇', birthday=Sat Feb 16 09:11:06 CST 1991}org.ko.prototype.clone.Pig2@6d6f6e28 Pig2{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}org.ko.prototype.clone.Pig2@135fbaa4
/** * 簡單的餓漢式單例 */ public class StaticInnerClassSingleton implements Cloneable { /** * 看靜態類的初始化鎖那個線程能夠拿到 */ private static class InnerClass { private static StaticInnerClassSingleton staticInnerClassSingleton = new StaticInnerClassSingleton(); } public static StaticInnerClassSingleton getInstance() { return InnerClass.staticInnerClassSingleton; } private StaticInnerClassSingleton() { if (InnerClass.staticInnerClassSingleton != null) { throw new RuntimeException("單例對象禁止反射調用"); } } /** * 直接重寫clone方法 * @return * @throws CloneNotSupportedException */ @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } public class Test { public static void main(String[] args) throws CloneNotSupportedException { //獲取單例對象 StaticInnerClassSingleton singleton = StaticInnerClassSingleton.getInstance(); System.out.println(singleton.toString()); //clone獲取克隆對象 StaticInnerClassSingleton singleton1 = (StaticInnerClassSingleton) singleton.clone(); System.out.println(singleton1.toString()); } }
org.ko.prototype.singleton.StaticInnerClassSingleton@1540e19d org.ko.prototype.singleton.StaticInnerClassSingleton@677327b6
/** * 簡單的餓漢式單例 */ public class StaticInnerClassSingleton1 implements Cloneable { /** * 看靜態類的初始化鎖那個線程能夠拿到 */ private static class InnerClass { private static StaticInnerClassSingleton1 staticInnerClassSingleton = new StaticInnerClassSingleton1(); } public static StaticInnerClassSingleton1 getInstance() { return InnerClass.staticInnerClassSingleton; } private StaticInnerClassSingleton1() { if (InnerClass.staticInnerClassSingleton != null) { throw new RuntimeException("單例對象禁止反射調用"); } } /** * 修改克隆方法,返回單例對象 * @return * @throws CloneNotSupportedException */ @Override protected Object clone() throws CloneNotSupportedException { return InnerClass.staticInnerClassSingleton; } } /** * 修改後的測試類 */ public class Test1 { public static void main(String[] args) throws CloneNotSupportedException { //獲取單例對象 StaticInnerClassSingleton1 singleton1 = StaticInnerClassSingleton1.getInstance(); System.out.println(singleton1.toString()); //獲取clone對象 StaticInnerClassSingleton1 singleton2 = (StaticInnerClassSingleton1) singleton1.clone(); System.out.println(singleton2.toString()); } }
org.ko.prototype.singleton.StaticInnerClassSingleton1@1540e19d org.ko.prototype.singleton.StaticInnerClassSingleton1@1540e19d
慕課網設計模式精講
: https://coding.imooc.com/class/270.html 設計模式之原型模式
: https://blog.csdn.net/chenliguan/article/details/69855738 C06 原型模式 示例(六) 原型模式破壞單例模式
: https://blog.csdn.net/weixin_33669968/article/details/88889565