原型模式(Prototype Pattern):使用原型实例指定建立对象的种类,而且经过拷贝这些原型建立新的对象。原型模式是一种对象建立型模式。git
原型模式的工做原理很简单:将一个原型对象传给那个要发动建立的对象,这个要发动建立的对象经过请求原型对象拷贝本身来实现建立过程。因为在软件系统中咱们常常会遇到须要建立多个相同或者类似对象的状况,所以原型模式在真实开发中的使用频率仍是很是高的。原型模式是一种“另类”的建立型模式,建立克隆对象的工厂就是原型类自身,工厂方法由克隆方法来实现。编程
须要注意的是经过克隆方法所建立的对象是全新的对象,它们在内存中拥有新的地址,一般对克隆所产生的对象进行修改对原型对象不会形成任何影响,每个克隆对象都是相互独立的。经过不一样的方式修改能够获得一系列类似但不彻底相同的对象。结构如图:设计模式
在原型模式结构图中包含以下几个角色:ide
1 对象的克隆方法函数
通用的克隆实现方法是在具体原型类的克隆方法中实例化一个与自身类型相同的对象并将其返回,并将相关的参数传入新建立的对象中,保证它们的成员属性相同。代码以下:ui
public class ConcretePrototype implements Prototype { private String attr; public String getAttr() { return attr; } public void setAttr(String attr) { this.attr = attr; } @Override public Prototype clone() { ConcretePrototype concretePrototype = new ConcretePrototype(); concretePrototype.setAttr(this.attr); return concretePrototype; } }
代码以下:this
class ConcretePrototype2 implements Cloneable { @Override public Prototype clone() { Object object = null; try { object = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return (Prototype) object; } }
2 浅克隆与深克隆的实现,代码以下:设计
public class WeeklyLog implements Cloneable,Serializable { private static final long serialVersionUID = 8532521622598526741L; private String name; private String content; private Attachment attachment; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Attachment getAttachment() { return attachment; } public void setAttachment(Attachment attachment) { this.attachment = attachment; } @Override //浅克隆,克隆出来的对象中的Attachment指向同一个对象地址 public WeeklyLog clone(){ Object obj; try { obj = super.clone(); return (WeeklyLog)obj; } catch(CloneNotSupportedException e) { System.out.println("不支持复制!"); return null; } } //深克隆,克隆出来的对象中的Attachment为不一样的对象 public WeeklyLog deepClone() throws IOException, ClassNotFoundException { //将对象写入流中 ByteArrayOutputStream bao=new ByteArrayOutputStream(); ObjectOutputStream oos=new ObjectOutputStream(bao); oos.writeObject(this); //将对象从流中取出 ByteArrayInputStream bis=new ByteArrayInputStream(bao.toByteArray()); ObjectInputStream ois=new ObjectInputStream(bis); return (WeeklyLog)ois.readObject(); } } class Attachment { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
Java语言提供的Cloneable接口和Serializable接口的代码很是简单,它们都是空接口,做为一种标识,本质上是调用的Object类的方法code
3 利用原型模式可实现一个原型管理器,专门负责克隆相应的对应,代码以下:
public class PrototypeManager { private static PrototypeManager instance = new PrototypeManager(); private Map<String, OfficialDocument> hm = new ConcurrentHashMap<>(); private PrototypeManager() { hm.put("far", new FAR()); hm.put("srs", new SRS()); } public PrototypeManager getInstance() { return instance; } //增长新的公文对象 public void addOfficialDocument(String key, OfficialDocument doc) { hm.put(key, doc); } //经过浅克隆获取新的公文对象 public OfficialDocument getOfficialDocument(String key) { return ((OfficialDocument) hm.get(key)).clone(); } } //抽象公文接口,也可定义为抽象类,提供clone()方法的实现,将业务方法声明为抽象方法 interface OfficialDocument extends Cloneable { OfficialDocument clone(); void display(); } //可行性分析报告(Feasibility Analysis Report)类 class FAR implements OfficialDocument { @Override public OfficialDocument clone() { OfficialDocument far = null; try { far = (OfficialDocument) super.clone(); } catch (CloneNotSupportedException e) { System.out.println("不支持复制!"); } return far; } @Override public void display() { System.out.println("《可行性分析报告》"); } } //软件需求规格说明书(Software Requirements Specification)类 class SRS implements OfficialDocument { @Override public OfficialDocument clone() { OfficialDocument srs = null; try { srs = (OfficialDocument) super.clone(); } catch (CloneNotSupportedException e) { System.out.println("不支持复制!"); } return srs; } @Override public void display() { System.out.println("《软件需求规格说明书》"); } }
用来复制一个对象,无需知道具体建立过程,可进行对象的浅克隆或深克隆。