原型模式

原型模式的定义:
 

用原型实例指定要创建的对象类型,通过复制这个实例创建新的对象
举一个例子(研磨设计模式中的例子)
例如现在有一个订单处理系统,接受订单对象,每个订单对象遵循相应的订单协议,即实现订单接口。
对于订单处理系统,只能接受订单数量小于1000的订单对象,如果订单对象的订单数量大于1000,则将该订单对象拆分成多个相同的订单对象
public interface OrderApi{
    //定义一些列订单操作,如订单数,订单放,日期等
}

public class PersonalOrder implements OrderApi{
    //私人订单
}
public class EnterpriseOrder implements OrderApi{
    //企业订单
}

public class OrderBusiness{
    public void saveOrder(OrderApi order){
    //业务需求,如果订单对象的订单数大于1000,要拆分成多个订单对象,每个订单对象的订单数不大于1000
    //1.判断订单对象的订单数是否大于1000
        while(order.orderNumber>1000){
            //如果订单数大于1000,拆分
            OrderApi newOrder = null;
            if(order instanceof PersonalOrder){
                PersonalOrder p2 = new PersonalOrder();
                personalOrder p1 = (PersonalOrder)order;
                p2.setParamaters(p1.getParameters);
                p2.setOrderNumber(1000);
                newOrder = p2;
            }
            if(order instanceof EnterpriseOrder){
                //与上面类似
            }
            //2.保存或处理新拆分元对象得到的新对象
            save(newOrder);
            order.setOrderNumber(order.orderNumber-1000);
        }
        //3.原订单对象的订单数已小于1000 可以直接处理保存。
        save(order);
    }
}
以上实现中,由于订单处理系统只接受订单接口,并不关心订单具体的实现,所以在拆分时,创建新的订单对象遇到麻烦,以上的
解决办法是通过instanceof判断订单类型。这样对于订单处理系统就必须知道所有的订单实现,也就是说订单处理系统和订单对象是
耦合在一起的,如果重新定义一个订单对象,势必重新改写订单处理系统的代码,即多加一个instanceof判断。

我们希望的实现是订单处理系统不关心订单对象有多少种实现,或者说我们的订单处理系统和订单是独立的,互不牵制。只要订单对象
实现订单接口,我们都能够对订单对象进行必要的处理如拆分和保存。如上代码,我们不用去判断订单对象到底属于何种类型。

原型模式可以解决此类问题。

在以上问题中,如果要拆分订单,得到新的订单对象,但并不知道订单对象的类型,如果使用原型模式,不必去判断订单类型,而是使用
复制,通过复制原型创建新的对象。通俗的讲,订单处理系统得到一个订单对象,发现他的订单数大于1000,需要拆分,复制原订单对象,
修改原订单对象和复制得到的对象的订单数。订单处理系统只知道原订单和复制对象都是接口类型。这样一来,不管新建多少个新的订单
对象,都不会影响订单系统的实现,实现了订单处理系统和订单对象的解耦合。
实现
public class PersonalOrder implements OrderApi{
    //私人订单
    //设置各种属性的方法
    //提供复制方法
    public OrderApi cloneOrder(){
        PersonalOrder order = new PersonalOrder();
        order.setParameters(this.parameters);
        return order;
    }
}

public class EnterpriseOrder implements OrderApi{
    //与PersonalOrder类似
}

public class OrderBusiness{
    public void saveOrder(OrderApi order){
        while(order.orderNumber > 1000){
            OrderApi newOrder = order.cloneOrder();
            newOrder.setOrderNumber(1000);
            order.setOrderNumber(order.orderNumber-1000);
            save(newOrder);
        }
        save(order);
    }
}

java中提供了clone()方法,只要类继承Cloneable接口,这个接口是一个标识接口,和序列化接口一样。复写其中的clone()方法即可
public Object clone(){
    Object obj = null;
    try{
        obj = super.clone();
    }catch(CloneNotSupportedException e){
        e.printStackTrace();
    }
    return obj;
}
不过复写的clone()方法返回Object类,在调用是还要在强制类型转换。
java中对于clone区分为深度克隆和浅度克隆
浅度克隆之是克隆按值传递的数据,如果某属性是引用类型,克隆无法完成引用类型的克隆,而只是复制引用,原对象和克隆对象
的引用共享同一个内存。(我的理解)
而深度克隆不仅克隆按值传递的数据,即使对于引用类型,要求该引用类型也必须实现cloneable接口,在深度克隆时,调用该
引用对象的clone方法克隆一个引用类型属性,如果该引用对象的属性仍然有引用类型,继续要求给引用类型实现Cloneable接口并
完成克隆,是一种递归克隆的过程,克隆出的对象和原对象的引用类型指向不同的内存,是两个不同的变量。


基于对象的克隆原型模式,实际上可以维护一个原型管理器,用于创建对象。
例如有一个原型接口:
public interface Prototype{//原型接口
    //原型方法:如setName setID getName
    public Prototype clone();
}

public class ConcretePrototype1 implements Prototype{//原型类
    //属性和方法定义
    public Prototype clone(){
        ConcretePrototype1 prototype = new Concretetype1();
        prototype.setName();
        return prototype;
    }
}
public class ConcretePrototype2 implements Prototype{
    //属性和方法定义
    public Prototype clone(){
        ConcretePrototype2 prototype = new Concretetype1();
        prototype.setName();
        return prototype;
    }
}
public class ConcretePrototype4 implements Prototype{
    //属性和方法定义
    public Prototype clone(){
        ConcretePrototype3 prototype = new Concretetype1();
        prototype.setName();
        return prototype;
    }
}
...
public class PrototypeManager{
    private static Map map = new HashMap();
    private PrototypeManager(){};//私有构造方法
    public synchronized static void regeistPrototye(String prototypeID,Prototype prototype){
        map.put(prototypeID,prototype);
    }
    public synchronized static void removePrototype(String prototypeID){
        map.remove(prototypeID);
    }
    public synchronized static Prototype getPrototype(String prototypeID) throws Exception{
        Prototype p = map.get(prototypeID);
        if(p == null){
            throw new Exception("此原型未注册")
        }
        return p;
    }
}

从原型管理器可以看出,原型模式应该是属于一种创建型的设计模式。
原文地址:https://www.cnblogs.com/brucemu/p/3113452.html