被说了很多遍的设计模式---原型模式

来源:互联网 发布:打扮家 知乎 编辑:程序博客网 时间:2024/05/01 15:08

[把你的理性思维慢慢变成条件反射]

本文,我们讲介绍原型模式,文章主题结构与上位一致。惯例,先来看看我们示例工程的环境:

操作系统:win7 x64

其他软件:eclipse mars,jdk7

-------------------------------------------------------------------------------------------------------------------------------------

经典问题:

对象复制,克隆。

思路分析:

要点一:支持浅克隆。

要点二:支持深克隆。

示例工程:


错误写法:

创建Templet.java文件,具体内容如下:

package com.csdn.ingo.gof_prototype;public class Window {public static void main(String[] args) {Templet a = new Templet("TempletA");a.setContext("AAAAA");a.setTime("010101");a.setCompany("CompanyA");Templet b = a;b.setName("TempletB");Templet c = a;c.setName("TempletC");a.display();b.display();c.display();System.out.println(a.hashCode());System.out.println(b.hashCode());System.out.println(c.hashCode());}}

错误原因:

首先,我们先观察上面main方法输出内容:

name:TempletC,context:AAAAA,time:010101,company:CompanyAname:TempletC,context:AAAAA,time:010101,company:CompanyAname:TempletC,context:AAAAA,time:010101,company:CompanyA171982551719825517198255
ABC三个对象在内存当中的地址完全相同,即代表同一个对象。(这部分概念非常基础,请各位看官牢记)。

推荐写法(1):浅克隆(值类型)


创建Prototype.java文件,具体内容如下:

package com.csdn.ingo.gof_prototype.one;public abstract class Prototype {private String id;public Prototype(String id){this.id=id;}public String getId() {return id;}public void setId(String id) {this.id = id;}public abstract Prototype Clone();}
创建ConcretePrototypeA文件,具体内容如下:

package com.csdn.ingo.gof_prototype.one;public class ConcretePrototypeA extends Prototype implements Cloneable {public ConcretePrototypeA(String id) {super(id);}@Overridepublic Prototype Clone() {return (Prototype) this.clone();}@Overridepublic Object clone() {ConcretePrototypeA cpa = null;try {cpa = (ConcretePrototypeA) super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return cpa;}}
创建Window.java文件,具体内容如下:

package com.csdn.ingo.gof_prototype.one;public class Window {public static void main(String[] args) {ConcretePrototypeA a = new ConcretePrototypeA("ingo");ConcretePrototypeA b = (ConcretePrototypeA)a.Clone();System.out.println(a.hashCode());System.out.println(b.hashCode());}}
观察输出:

114919720761102

推荐写法(2):浅克隆(引用类型)


创建Collection.java文件,具体内容如下:

package com.csdn.ingo.gof_prototype.two;import com.csdn.ingo.gof_prototype.one.ConcretePrototypeA;public class Collection implements Cloneable {private String prop1;private String prop2;public String getProp1() {return prop1;}public void setProp1(String prop1) {this.prop1 = prop1;}public String getProp2() {return prop2;}public void setProp2(String prop2) {this.prop2 = prop2;}@Overridepublic Object clone() {Collection co = null;try {co = (Collection) super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return co;}}
创建ConcretePrototypeA.java文件,具体内容如下:
package com.csdn.ingo.gof_prototype.two;public class ConcretePrototypeA extends Prototype implements Cloneable {private Collection collection =new Collection();public Collection getCollection() {return collection;}public void setCollection(Collection collection) {this.collection = collection;}public ConcretePrototypeA(String id) {super(id);}@Overridepublic Prototype Clone() {return (Prototype) this.clone();}@Overridepublic Object clone() {ConcretePrototypeA ca = null;try {ca = (ConcretePrototypeA) super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return ca;}}
创建Prototype.java文件,具体内容如下:

package com.csdn.ingo.gof_prototype.two;public abstract class Prototype {private String id;public Prototype(String id){this.id=id;}public String getId() {return id;}public void setId(String id) {this.id = id;}public abstract Prototype Clone();}
创建Window.java文件,具体内容如下:

package com.csdn.ingo.gof_prototype.two;public class Window {public static void main(String[] args) {ConcretePrototypeA a = new ConcretePrototypeA("ingo");ConcretePrototypeA b = (ConcretePrototypeA)a.Clone();Collection ca = a.getCollection();ca.setProp1("a1");ca.setProp2("a2");Collection cb = b.getCollection();cb.setProp1("b1");cb.setProp2("b2");System.out.println(a.hashCode());System.out.println(b.hashCode());System.out.println(a.getCollection().hashCode());System.out.println(b.getCollection().hashCode());}}
观察输出:

1396421151050423116477031164770

推荐写法(3):深克隆(专用)


创建Colleation.java文件,具体内容如下:

package com.csdn.ingo.gof_prototype.three;import com.csdn.ingo.gof_prototype.two.ConcretePrototypeA;public class Collection implements Cloneable{private String date;private String company;public String getDate() {return date;}public void setDate(String date) {this.date = date;}public String getCompany() {return company;}public void setCompany(String company) {this.company = company;}@Overridepublic Object clone(){Collection ca = null;try {ca = (Collection) super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return ca;}@Overridepublic String toString() {return "Collection [date=" + date + ", company=" + company + "]";}}
创建Prototype.java文件,具体内容如下:
package com.csdn.ingo.gof_prototype.three;public class Prototype implements Cloneable {private String name;private Collection work;public Prototype(String name){this.name = name;work = new Collection();}private Prototype(Collection work){this.work = (Collection)work.clone();}public String getName() {return name;}public void setName(String name) {this.name = name;}public Collection getWork() {return work;}public void setWork(Collection work) {this.work = work;}public void setWke(String date,String company){work.setDate(date);work.setCompany(company);}@Overridepublic String toString() {return "Prototype [name=" + name + ", work=" + work.toString() + "]";}@Overridepublic Object clone(){Prototype ca = new Prototype(this.work);ca.setName(name);return ca;}}
创建Window.java文件,具体内容如下:
package com.csdn.ingo.gof_prototype.three;public class Window {public static void main(String[] args) {Prototype a = new Prototype("ingo");System.out.println(a.hashCode());a.setWke("01", "aaa");Prototype b = (Prototype)a.clone();System.out.println(b.hashCode());b.setWke("02", "bbb");Prototype c = (Prototype)a.clone();System.out.println(c.hashCode());c.setWke("03", "ccc");System.out.println(a.toString());System.out.println(b.toString());System.out.println(c.toString());}}

推荐写法(4):深克隆(通用)


创建Collection.java文件,具体内容如下:

package com.csdn.ingo.gof_prototype.four;import java.io.Serializable;public class Collection implements Serializable {private static final long serialVersionUID = 1L;private String date;private String company;public String getDate() {return date;}public void setDate(String date) {this.date = date;}public String getCompany() {return company;}public void setCompany(String company) {this.company = company;}@Overridepublic Object clone() {Collection ca = null;try {ca = (Collection) super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return ca;}@Overridepublic String toString() {return "Collection [date=" + date + ", company=" + company + "]";}}

创建Prototype.java文件,具体内容如下;

package com.csdn.ingo.gof_prototype.four;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;public class Prototype implements Serializable {private static final long serialVersionUID = 1L;private String name;private Collection work;public Prototype(String name) {this.name = name;work = new Collection();}public String getName() {return name;}public void setName(String name) {this.name = name;}public Collection getWork() {return work;}public void setWork(Collection work) {this.work = work;}public void setWke(String date, String company) {work.setDate(date);work.setCompany(company);}@Overridepublic String toString() {return "Prototype [name=" + name + ", work=" + work.toString() + "]";}public Prototype clone() {ByteArrayOutputStream bao = new ByteArrayOutputStream();ObjectOutputStream oos;try {oos = new ObjectOutputStream(bao);oos.writeObject(this);ByteArrayInputStream bis = new ByteArrayInputStream(bao.toByteArray());ObjectInputStream ois;ois = new ObjectInputStream(bis);return (Prototype) ois.readObject();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}return null;}}
创建Window.java文件,具体内容如下:

package com.csdn.ingo.gof_prototype.four;public class Window {public static void main(String[] args) {Prototype a = new Prototype("ingo");System.out.println(a.hashCode());a.setWke("01", "aaa");Prototype b = (Prototype)a.clone();System.out.println(b.hashCode());b.setWke("02", "bbb");Prototype c = (Prototype)a.clone();System.out.println(c.hashCode());c.setWke("03", "ccc");System.out.println(a.toString());System.out.println(b.toString());System.out.println(c.toString());}}<span style="font-family:Microsoft YaHei;font-size:14px;"></span>

问题:浅克隆与深克隆的区别?

浅克隆:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。换句话说:对象成员变量中的简单类型都被复制,而引用对象类型,只复制引用,仍然指向原有对象,该对象仍然只有一份。

深克隆:被复制对象的所有变量都含有与原来的对象相同的值,所有的对其他对象的引用也复制一份引用的对象。换句话说:对象成员变量中的简单类型都被复制,而引用对象类型,不止复制引用,而是将引用对象也复制一份。

模式总结:

标准UML结构图:


概念总结:

原型模式:用原型实例指定创建对象的种类,并且通过开配这些原型创建新的对象。

组成部分:Prototype(原型类),ConcretePrototype(具体子类)两部分组成。

注:本文仅以Java为例说明,其他语言的原型模式,请各位看官自行学习。

反思:

应用场景:

  1. 创建相似的对象。
  2. 在上面的基础之上,创建新对象的花费资源较多,耗时较长的场景。
  3. 对象变化较小,并需要长时间保存时,在系统内创建备份时。
  4. 对象中含有组合属性,并且对象数量较少,考虑执行效率时。

优点:

  1. 当对象较为复杂,通过原型模式可以简化创建过程,提高创建效率。
  2. 扩展性好。客户端直接与抽象类进行交互,提高了双方的灵活性,扩展性。
  3. 提供深克隆,浅克隆两种方式供其使用。

缺点:

  1. 必须要为每一个对象创建一个克隆方法,克隆对象的任何改变,将直接违反“开闭原则”。
  2. 深克隆的过程需要IO等多个复杂过程。需要及时处理异常情况。
  3. 深层嵌套的克隆难于管理及实现。

-------------------------------------------------------------------------------------------------------------------------------------

至此,被说了很多遍的设计模式---原型模式 结束


参考资料:

图书:《大话设计模式》

其他博文:http://blog.csdn.NET/lovelion/article/details/7563445


1 0
原创粉丝点击