原始模型模式属于对象的创建模式。通过一个原型对象来指明要创建对象的类型,然后用复制原型对象的方法来创建出更多同类型的对象。
Java所有的类都是从java.lang.Object类继承来的,Object类提供clone()方法对对象进行复制。一般调用clone()方法需要满足一下条件:
1、对于任何对象x,都有:x.clone()!=x。也就是克隆的对象和原对象不是一个对象。
2、对于任何对象x,都有:x.clone().getClass()=x.getClass()。也就是克隆对象与原对象是相同的类型。
3、如果对象x的equal()方法定义恰当的话,那么x.clone().equal(x)应该成立。
原始模型模式分为两种类型:1、简单形式;2、登记形式。下面分别解释下这两种类型。
简单形式的原始模型模式类图:
这种模式的三个角色:
1、客户角色:客户提出创建对象的请求。
2、抽象原型:抽象角色,给出具体原型所需的接口。
3、具体原型:被复制的对象,需实现抽象原型所需要的接口。
抽象原型代码:
1 public interface Prototype extends Cloneable{ 2 public Object clone() throws CloneNotSupportedException; 3 }
具体原型代码:
1 public class ConcrecePrototype implements Prototype{ 2 public Object clone() throws CloneNotSupportedException { 3 try { 4 return super.clone(); 5 } catch (Exception e) { 6 return null; 7 } 8 } 9 }
客户角色代码:
1 public class Client { 2 private Prototype prototype; 3 public void operation(Prototype example) throws CloneNotSupportedException{ 4 Prototype p = (Prototype) example.clone(); 5 } 6 }
登记形式的原始模型模型类图:
这种模式的角色:
1、客户角色:客户提出创建对象的请求。
2、抽象原型:抽象角色,给出具体原型所需的接口。
3、具体原型:被复制的对象,需实现抽象原型所需要的接口。
4、原型管理器:创建具体原型类对象,并记录每一个被创建的对象。
抽象原型代码:
1 public interface Prototype extends Cloneable{ 2 public Object clone() throws CloneNotSupportedException; 3 }
具体原型代码:
1 public class ConcrecePrototype implements Prototype{ 2 public synchronized Object clone() throws CloneNotSupportedException { 3 Prototype temp = null; 4 try { 5 temp = (Prototype) super.clone(); 6 } catch (Exception e) { 7 System.out.println("clone fail"); 8 }finally{ 9 return temp; 10 } 11 } 12 }
原型管理器代码:
1 public class PrototypeManager { 2 private Vector vector = new Vector(); 3 4 public void add(Prototype e){ 5 vector.add(e); 6 } 7 8 public Prototype get(int i){ 9 return (Prototype) vector.get(i); 10 } 11 }
客户端代码:
1 public class Client { 2 private PrototypeManager pm; 3 private Prototype p; 4 5 public void registerPrototype(Prototype prototype) throws CloneNotSupportedException{ 6 Prototype temp = (Prototype) prototype.clone(); 7 pm.add(temp); 8 } 9 }
可以看出,如果要创建的原型对象少且固定的话可以考虑使用简单形式的原型模式。如果要创建的原型对象不固定,可以使用登记形式的原型模式。原型对象有原型管理器保管,如果其中有则直接拿出,没有则复制并加入其中。
看到这里就会想到了java中重要的话题:浅复制和深复制。
浅复制:被复制对象的所有变量都与原来对象有相同的值,而所有对其对象的引用都指向原对象。浅复制只考虑复制所考虑的对象,而不复制它所引用的对象。
深复制:被复制对象的所有变量都与原来对象有相同的值,那些引用其他对象的变量指向被复制的新对象。深复制中那些引用其他对象的变量将指向被复制过的新对象,也就是深复制把要复制的对象所引用的对象都复制了一遍。
优点:
1、 原始模型模型模式允许动态地增加或减少产品类。由于创建产品类实例的方法是产品类内部具有的,因此,增加新产品的对整个结构没有影响。
2、 原始模型模式提供简化的创建结构。工厂方法模式常常需要有一个与产品类等级相同的结构,而原始模型模式就不需要这样。
3、 具有给一个应用软件动态加载新功能的能力。
4、 产品类不需要非得有任何事先确定的等级结构,因为原始模型模式适用于任何的等级。
缺点:
原始模型模式最主要的缺点就是需要为每一个类都必须具备一个复制方法。
另外,如果在原型对象中有间接对象,可以将间接对象设置为transient不予以复制,或者自行创建出相当的同种对象。