定义
用原型实例制定创建对象的种类,并通过拷贝这些原型创建新的对象。结构和说明
Prototype:声明一个克隆自身的接口,用来约束想要克隆自己的类,要求他们都要实现这里定义的克隆方法。
ConcretePrototype:实现Prototype接口的类,这些类真正实现克隆自身的功能。
Client:使用原型的客户端,首先获取到原型实例对象,然后通过原型实例克隆自身来创建新的对象实例。引入实例 订单处理
实现一个统一通用的订单处理的模型。
每当订单的预定产品数量超过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) } } }
原型模式
通过克隆来创建的对象实例,并且新克隆出来的对象实例复制原型实例的属性的值。
原型实例和克隆实例 本质上是不同的实例,克隆完成后,他们之间是没有关联的,克隆出来的属性值发生改变是不会影响原型实例的。- 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; } }
- java中的克隆方法
原型优缺点
a. 对客户端隐藏具体实现类型
b. 在运行时动态改变具体的实现类型
c. 深度克隆实现比较困难原型模式本质
克隆生成对象使用场景
如果一个系统想要独立于它想要使用的对象时,可以使用原型模式,让系统只面向接口编程,在系统需要新对象的时候,可以通过克隆原型来得到。
如果需要实例化的类是在运行时刻动态指定时,可以使用原型模式。
设计模式之原型模式
最新推荐文章于 2024-06-13 09:51:08 发布