设计模式:原型模式
定义
原型模式的定义:Specify the kinds of objects to create using a prototypical instance,and create new objects by copying this prototype.(用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。)
结构类图
原型模式的通用类图:
原型模式非常简单,它的核心是一个clone方法,通过该方法完成对象的拷贝,在Java中只需要实现Cloneable接口,并且覆盖Object类的clone方法。
通用源码
原型模式的通用源码:
public class PrototypeClass implements Cloneable {
//覆写父类Object方法
@Override
protected PrototypeClass clone() {
PrototypeClass prototypeClass = null;
try {
prototypeClass = (PrototypeClass) super.clone();
} catch (CloneNotSupportedException e) {
// 异常处理
}
return prototypeClass;
}
}
实现Cloneable接口,然后重写clone方法,就完成了原型模式!
应用场景举例
比如客户提供订单交给工厂处理。订单有产品的数量和名称,公司接受订单后需要保存最原始的数据作为存根。公司每个部门在一个订单内最多只能生产1000个产品,所以需要将原始订单进行拆分,然后处理。
抽象订单类IOrder,定义订单数量和clone操作:
public interface IOrder extends Cloneable {
int getOrderNumber();
void setOrderNumber(int orderNumber);
IOrder clone();
}
产生两个订单实现类,个人订单类PersonalOrder:
public class PersonalOrder implements IOrder {
private String orderName;
private int orderNumber;
@Override
public int getOrderNumber() {
return orderNumber;
}
@Override
public void setOrderNumber(int orderNumber) {
this.orderNumber = orderNumber;
}
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
@Override
public IOrder clone() {
IOrder order = null;
try {
order = (IOrder) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return order;
}
}
公司订单类CompanyOrder:
public class CompanyOrder implements IOrder {
private String orderName;
private int orderNumber;
@Override
public int getOrderNumber() {
return orderNumber;
}
@Override
public void setOrderNumber(int orderNumber) {
this.orderNumber = orderNumber;
}
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
@Override
public IOrder clone() {
IOrder order = null;
try {
order = (IOrder) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return order;
}
}
订单处理类OrderDealFactory,将原始订单进行拆分处理:
public class OrderDealFactory {
public void dealOrder(IOrder order) {
int number = order.getOrderNumber();
while (number > 0) {
/**
* 如果不使用原型模式,需要根据实际类型new对象,来保存原始数据
if (order instanceof PersonalOrder) {
IOrder iOrder = null;
PersonalOrder personalOrder = (PersonalOrder) order;
PersonalOrder newOrder = new PersonalOrder();
newOrder.setOrderName(personalOrder.getOrderName());
newOrder.setOrderNumber(number >= 1000 ? 1000 : number);
iOrder = personalOrder;
System.out.println("原始订单: " + iOrder.getOrderNumber());
System.out.println("newOrder number = " + newOrder.getOrderNumber());
number -= 1000;
}
*/
IOrder newOrder = (IOrder) order.clone();
newOrder.setOrderNumber(number >= 1000 ? 1000 : number);
System.out.println("原始订单: " + order.getOrderNumber());
System.out.println("newOrder number = " + newOrder.getOrderNumber());
number -= 1000;
}
}
}
场景类的调用方法如下:
public class Client {
public static void main(String[] args) {
OrderDealFactory factory = new OrderDealFactory();
PersonalOrder order = new PersonalOrder();
order.setOrderName("个人订单");
order.setOrderNumber(3200);
factory.dealOrder(order);
}
}
浅拷贝、深拷贝
Object类的clone方法的原理是从内存中(具体地说就是堆内存)以二进制流的方式进行拷贝,重新分配一个内存块。所以是浅拷贝,拷贝对象内部的引用对象是不会被拷贝的。即:浅拷贝前后的对象,内部的数组和引用对象,指向的还是同一片内存。
总结
- 原型模式是在内存二进制流的拷贝,要比直接new一个对象性能好很多。
- 在上面的例子中,增加一个订单类,订单处理类不需要修改,符合开闭原则。