• 原型模式


    原型模式的定义:
     

    用原型实例指定要创建的对象类型,通过复制这个实例创建新的对象
    举一个例子(研磨设计模式中的例子)
    例如现在有一个订单处理系统,接受订单对象,每个订单对象遵循相应的订单协议,即实现订单接口。
    对于订单处理系统,只能接受订单数量小于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;
        }
    }

    从原型管理器可以看出,原型模式应该是属于一种创建型的设计模式。
  • 相关阅读:
    leetcode950
    leetcode938
    leetcode953
    推荐系统那点事儿
    极大似然估计的理解与应用
    吴恩达机器学习笔记 —— 1 绪论:初识机器学习
    吴恩达机器学习笔记 —— 3 线性回归回顾
    吴恩达机器学习笔记 —— 5 多变量线性回归
    吴恩达机器学习笔记 —— 7 Logistic回归
    吴恩达机器学习笔记 —— 8 正则化
  • 原文地址:https://www.cnblogs.com/brucemu/p/3113452.html
Copyright © 2020-2023  润新知