原始模型模式属于对象的创建模式。通过一个原型对象来指明要创建对象的类型,然后用复制原型对象的方法来创建出更多同类型的对象。
原始模型模式与java联系非常紧密,因为java天生就支持原始模型模式。java的Object类声明了一个clone()方法,该方法就是用来复制对象的,方法定义如下:
在Java中所有类均继承自java.lang.Object,同样也就拥有了clone()方法,下面是java.util.ArrayList类中对clone()方法的实现,如下图:
上图中,调用ArrayList的clone()方法复制一个新的ArrayList对象,然后使用Arrays类的copyOf方法将ArrayList内部的elementData数组的数据拷贝到新克隆的ArrayList对象上面。
Java所有的类都是从java.lang.Object类继承来的,Object类提供clone()方法对对象进行复制。一般调用clone()方法需要满足一下条件:
对于任何对象x都有:x.clone()!=x。也就是克隆的对象和原对象不是一个对象。
对于任何对象x都有:x.clone().getClass()=x.getClass()。也就是克隆对象与原对象是相同的类型。
如果对象x的equal()方法定义恰当的话,那么x.clone().equal(x)应该成立。
浅复制只复制对象的基础类型(如:int、long、char等),如果是对象类型,则只复制对象的引用(如:ArrayList、HashMap等等)。如下图:
上图中,"对象"中的book对象在复制后"复制对象"指向同一个Book对象。
深复制不仅复制对象的基本类,同时也复制原对象中的对象,完全产生新对象。如下图:
上图中,"对象"和"复制对象"都指向新的Book对象。
原始模型模式分为两种类型:
简单形式
登记形式
简单形式的原始模型模式类图:
这种模式的三个角色:
客户角色:客户提出创建对象的请求。
抽象原型:抽象角色,给出具体原型所需的接口。
具体原型:被复制的对象,需实现抽象原型所需要的接口。
Java实例代码:
// 抽象原型代码 public interface Prototype extends Cloneable{ public Object clone() throws CloneNotSupportedException; } // 具体原型代码 public class ConcrecePrototype implements Prototype{ public Object clone() throws CloneNotSupportedException { try { return super.clone(); } catch (Exception e) { return null; } } } // 客户端代码 public class Client { public static void main(String[] args) throws CloneNotSupportedException { Prototype example = new ConcrecePrototype(); Prototype p = (Prototype) example.clone(); } }
上面ConcrecePrototype类实现了抽象原型接口Prototype,然后简单的实现了clone方法,该方法将克隆一个Prototype对象的新实例,根据实现clone方法的方式不同,分为浅克隆和深克隆。
这种模式的角色:
客户角色:客户提出创建对象的请求。
抽象原型:抽象角色,给出具体原型所需的接口。
具体原型:被复制的对象,需实现抽象原型所需要的接口。
原型管理器:创建具体原型类对象,并记录每一个被创建的对象。
Java代码如下:
// 抽象原型代码 public interface Prototype extends Cloneable{ public Object clone() throws CloneNotSupportedException; } // 具体原型代码 public class ConcrecePrototype implements Prototype{ public synchronized Object clone() throws CloneNotSupportedException { Prototype temp = null; try { temp = (Prototype) super.clone(); } catch (Exception e) { System.out.println("clone fail"); }finally{ return temp; } } } // 原型管理器代码 public class PrototypeManager { private Vector vector = new Vector(); public void add(Prototype e){ vector.add(e); } public Prototype get(int i){ return (Prototype) vector.get(i); } } // 客户端代码 public class Client { private PrototypeManager pm; private Prototype p; public void registerPrototype(Prototype prototype) throws CloneNotSupportedException{ Prototype temp = (Prototype) prototype.clone(); pm.add(temp); } }
可以看出,如果要创建的原型对象少且固定的话可以考虑使用简单形式的原型模式。如果要创建的原型对象不固定,可以使用登记形式的原型模式。原型对象有原型管理器保管,如果其中有则直接拿出,没有则复制并加入其中。