场景:
一个订单系统,里面有一个保存订单的业务功能。具体需求:每当订单的预订产品超过1000的时候,需要把订单拆分
成两份订单。如果拆分成两份后还是超过1000,则继续拆分。订单类型分为个人订单和公司订单,不管是什么类型的订
单,都要能够正常地处理.抽象的描述下就是已经有了某个对象实例后,如何能够快速的创建出更多的这种对象。
定义:
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
角色:
Prototype: 声明一个克隆自身的接口,用来约束想要克隆自己的类,要求他们都要实现这里定义的克隆方法。
package com.kris.study; public interface Prototype { public Prototype cloneItem(); public void display(); }
ConcretePrototype:实现Prototype接口的类,这些类真正实现了克隆自身的功能
package com.kris.study; public class ConcretePrototype2 implements Prototype { @Override public Prototype cloneItem() { return new ConcretePrototype2(); } @Override public void display() { System.out.println("ConcretePrototype2 display"); } }
package com.kris.study; public class ConcretePrototype1 implements Prototype { @Override public Prototype cloneItem() { return new ConcretePrototype1(); } @Override public void display() { System.out.println("ConcretePrototype1 display"); } }
Client客户端:
package com.kris.study; public class Client { private Prototype prototype; public Client(Prototype prototype){ this.prototype = prototype; } public void operation(){ Prototype newPrototype = prototype.cloneItem(); newPrototype.display(); } }
使用JAVA中的克隆方法实现原型模式解决场景的问题:
Order:订单类
package com.kris.study; public abstract class Order implements Cloneable{ private String productId; private int orderProductNum = 0; public abstract void setName(String name); public abstract String display(); public String getProductId() { return productId; } public void setProductId(String productId) { this.productId = productId; } public int getOrderProductNum() { return orderProductNum; } public void setOrderProductNum(int orderProductNum) { this.orderProductNum = orderProductNum; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } }
PersonalOrder:个人订单类
package com.kris.study; public class PersonalOrder extends Order { private String personalName; @Override public String display() { return "PersonalName:"+personalName; } @Override public void setName(String name) { this.personalName = name; } }
EnterpriseOrder:公司订单类
package com.kris.study; public class EnterpriseOrder extends Order { private String enterpriseName; @Override public String display() { return "EnterpriseName:"+enterpriseName; } @Override public void setName(String name) { this.enterpriseName = name; } }
OrderBiz:订单业务
package com.kris.study; public class OrderBiz { public void saveOrder(Order order){ while(order.getOrderProductNum()>1000){ try { Order newOrder = (Order) order.clone(); newOrder.setOrderProductNum(1000); order.setOrderProductNum(order.getOrderProductNum()-1000); System.out.println("new order info ==> name: "+newOrder.display()+" productId:" +newOrder.getProductId()+" productNum:"+newOrder.getOrderProductNum()); } catch (CloneNotSupportedException e) { e.printStackTrace(); } } System.out.println("old order info ==> name: "+order.display()+" productId:" +order.getProductId()+" productNum:"+order.getOrderProductNum()); } }
Client:客户端
package com.kris.study; public class Client { public static void main(String[] args) { Order order = new PersonalOrder(); order.setName("John"); order.setProductId("111"); order.setOrderProductNum(3422); new OrderBiz().saveOrder(order); } }
深克隆和浅克隆
浅克隆:只负责克隆按值传递的数据(比如基本数据类型,String类型)。
深克隆:除了浅克隆要克隆的值外,还负责克隆引用类型的数据。
引用类型需要递归实现Cloneable接口。
JAVA中实现深克隆:
package com.kris.study; public class Product implements Cloneable { private String productId; private String name; public String getProductId() { return productId; } public void setProductId(String productId) { this.productId = productId; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Product [productId=" + productId + ", name=" + name + "]"; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } }
package com.kris.study; public class PersonalOrder implements Cloneable { private String customerName; private Product product = null; public String getCustomerName() { return customerName; } public void setCustomerName(String customerName) { this.customerName = customerName; } public Product getProduct() { return product; } public void setProduct(Product product) { this.product = product; } @Override public String toString() { return "PersonalOrder [customerName=" + customerName + ", product=" + product + "]"; } @Override public Object clone() throws CloneNotSupportedException { PersonalOrder obj = (PersonalOrder) super.clone(); //关键的一句话 obj.setProduct((Product) this.product.clone()); return obj; } }
原理分析:
本质:克隆生成新对象
优点:对客户端隐藏具体实现
缺点:每个原型的子类必须实现clone的操作。