设计模式之原型模式

  1. 定义
    用原型实例制定创建对象的种类,并通过拷贝这些原型创建新的对象。

  2. 结构和说明

    这里写图片描述

    Prototype:声明一个克隆自身的接口,用来约束想要克隆自己的类,要求他们都要实现这里定义的克隆方法。
    ConcretePrototype:实现Prototype接口的类,这些类真正实现克隆自身的功能。
    Client:使用原型的客户端,首先获取到原型实例对象,然后通过原型实例克隆自身来创建新的对象实例。

  3. 引入实例 订单处理

    实现一个统一通用的订单处理的模型。
    每当订单的预定产品数量超过1000的时候,就需要把订单拆成两份订单来保存,如果拆成两份订单后,还是超过1000那就继续拆分。目前的订单类型被分成两种:一种是个人订单,一种是公司订单。

    public interface OrderApi{
        int getOrderProductNum();
        void setOrderProductNum(int productNum);
        OrderApi cloneOrder();
    }
    
    public class PersonalOrder implements OrderApi{
        private String customerName;
        private String productId;
        private Integer productNum = 0;
    
        public int getOrderProductNum(){
            return this.productNum;
        }
        public void setOrderProductNum(int productNum){
            this.productNum = productNum;
        }
        public OrderApi cloneOrder(){
            PersonalOrder orderApi = new PersonalOrder();
            orderApi.setCustomerName(this.customName);
            orderApi.setProductNum(this.productNum);
            orderApi.setProductId(this.productId);
            return orderApi;
        }
        public String toString(){}
    }
    
        public class EnterpriseOrder implements OrderApi{
        private String enterpriseName;
        private String productId;
        private Integer productNum = 0;
    
        public int getOrderProductNum(){
            return this.productNum;
        }
        public void setOrderProductNum(int productNum){
            this.productNum = productNum;
        }
        public OrderApi cloneOrder(){
            EnterpriseOrder orderApi = new EnterpriseOrder();
            orderApi.setEnterpriseName(this.enterpriseName);
            orderApi.setProductNum(this.productNum);
            orderApi.setProductId(this.productId);
            return orderApi;
        }
        public String toString(){}
    }
    //两种订单例子
    
    
    //使用常用方法
    public class OrderBusiness{
        private final static LIMIT_NUM = 1000;
        public void saveOrder(OrderApi order) {
            while(order.getOrderProductNum() > LIMIT_NUM){
                OrderApi newOrder = null;
                //使用instanceOf 关键字判断是那种逻辑的订单做处理
                if (order instanceOf PersonalOrder) {
                    PersonalOrder p2 = new PersonalOrder();
                    PersonalOrder p1 =(PersonalOrder)order;
                    p2.setCustomerName(p1.getCustomerName());
                    p2.setProductId(p1.getProductId);
                    p2.setOrderProductNum(1000);
                    newOrder = p2;
                } else if (order instanceOf EnterpriseOrder){
                EnterpriseOrder e2 = new EnterpriseOrder();
                    EnterpriseOrder e1 =(EnterpriseOrder)order;
    
    e2.setCustomerName(e1.getCustomerName());
                    e2.setProductId(e1.getProductId);
                    e2.setOrderProductNum(1000);
                    newOrder = e2;
                }
            } 
        }
        //问题:想实现通用的订单处理,对于订单处理的对象是不应该知道订单的具体实现,更不应该依赖订单的具体实现。instanceOf 很明显关联业务处理对象;通用订单处理,当扩展新类型的订单,需修改原有的逻辑。引入**已经有了某个对象实例,如何能够快速简单的创建这种对象**      
    }
    
    public class OrderBusinessPro{
        private final static LIMIT_NUM = 1000;
        public void saveOrder(OrderApi order) {
            //判断产品数量是否大于1000
            while(order.getProductNum() > LIMIT_NUM){
                //正常不用模式一般会使用instanceOf判断不属于那种类型重新new对象copy值
                OrderApi newOrder = order.cloneOrder();
                newOrder.setProductNum(LIMIT_NUM);
                order.setProductNum(order.getProductNum()-LIMIT_NUM)
            }
        }
    }
  4. 原型模式
    通过克隆来创建的对象实例,并且新克隆出来的对象实例复制原型实例的属性的值。
    原型实例和克隆实例 本质上是不同的实例,克隆完成后,他们之间是没有关联的,克隆出来的属性值发生改变是不会影响原型实例的。

    • java中的克隆方法
      Java中已经提供了clone方法,定义在object类中,只需要实现java.lang.Cloneable 接口(标示接口)。
    public class PersonalOrder implements Cloneable,OrderApi{
        //属性
        private String customerName;
        private String productId;
        private Integer productNum = 0;
        public Object clone(){
            Object obj = null;
            try{
                //java Object 类clone
                obj = super.clone();
            }catch(CloneNotSupportedException e){
                e.printStackTrace();
            }
            return obj;
        }
    }
    • 浅度克隆和深度克隆
      浅度克隆:只负责克隆按值传递的数据。
      深度克隆:除了浅度克隆要克隆的值外,还负责克隆引用类型的数据,基本就是克隆所有属性的数据都会被克隆出来。
    public interface ProductPrototype {
        ProductPrototype cloneProduct();
    }
    public class product implements ProductPrototype{
        private String name;
        private String productId;
    
        public ProductPrototype cloneProduct(){
            Product p = new Product();
            p.setName(this.name);
            p.setProductId(this.productId);
            return p;
        }
    }
    //自行实现克隆    
    public class EnterpriseOrder implements OrderApi{
        private String enterpriseName;
        //引用类型
        private Product product;
        private Integer productNum = 0;
        //get set略
        public OrderApi cloneOrder(){
            EnterpriseOrder orderApi = new EnterpriseOrder();
            orderApi.setEnterpriseName(this.enterpriseName);
            orderApi.setProductNum(this.productNum);
            //对象类型数据,深度克隆需要继续调用这个对象的克隆方法
            Product p = (Product)this.product.cloneProduct();
            orderApi.setProduct(p);
            return orderApi;
        }
    }
    
    //使用jdk实现克隆 
    public class EnterpriseOrder implements OrderApi{
        private String enterpriseName;
        //引用类型
        private Product product;
        private Integer productNum = 0;
        //get set略
        public Object clone(){
            EnterpriseOrder orderApi = null;
            try{
                obj = (EnterpriseOrder)super.cloneProduct();
                obj.setProduct((Product)this.product.clone();)
            } catch(Exception e){
                e.printStackTrace();
            }
            return obj;
        }
    }   
    • 原型管理器
      在系统中维护一个当前可用的原型注册表。比如系统中的原型可以被动态的创建和销毁。原型管理器缓存和管理原型实例。
    public class PrototypeManager{
        private static Map<String,Prototype> manager = new HashMap<String,Prototype>();
        private PrototypeManager(){};
    
        public synchronized static void setPrototype(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) {
            Prototype prototype = map.get(prototypeId);
            if (prototype == null) {
                throw new Exception("您希望获取的原型还没注册或已被销毁")
            }
            return prototype;
        }
    } 
  5. 原型优缺点
    a. 对客户端隐藏具体实现类型
    b. 在运行时动态改变具体的实现类型
    c. 深度克隆实现比较困难

  6. 原型模式本质
    克隆生成对象

  7. 使用场景
    如果一个系统想要独立于它想要使用的对象时,可以使用原型模式,让系统只面向接口编程,在系统需要新对象的时候,可以通过克隆原型来得到。
    如果需要实例化的类是在运行时刻动态指定时,可以使用原型模式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值