- Published on
prototype 原型模式
原型模式
顾名思义,其实说白了,就是让一个对象可以自己拷贝自己,对象把自己当成一个原型,然后提供一个方法出去,外部要一个对象的克隆和拷贝,直接就copy一份就可以了,但是这里要记住深拷贝和浅拷贝的区别。
因为一个对象 可能还持有别的对象的引用,浅拷贝就是不管引用的其他对象了;深拷贝就是将引用的对象也一起拷贝一份;一般原型模式都是要支持深拷贝的。且其实一般实现原型模式的时候,直接是通过覆盖Object类的clone()方法即可,在里面实现自己的拷贝逻辑就可以了。
使用原型模式比较好的一点,就是如果别人要拷贝你的对象,不需要调用方自己实现拷贝逻辑,将拷贝逻辑放在对象自己身体里就可以了,对外面调用都是透明的。
这个模式其实在我们的电商系统中,完全有场景可以使用,可以想象一下,比如我们的这个订单、发货单、销售出库单、财务结算单,这些单子之间,可能就是有大量的属性是要互相拷贝的。我们手上有一个订单之后,想将订单中的数据拷贝到一个发货单中,将发货单中的属性拷贝到一个销售出库单中,再将销售出库单中的属性拷贝到财务结算单中。
这种大量的属性拷贝的业务场景,我们就可以对原型模式进行改造,我们可以实现一个适合自己系统的通用的对象属性拷贝工具类,然后对那些需要互相之间支持属性拷贝的类,我们可以重写其clone()方法,这个我们后面再讲解,发货单的clone()方法,调用之后,克隆出来的是一个销售出库单。
一般模式
package wang.jinggo.basics.zhss.prototype;
/**
* @author: wangyj
* @create: 2021-10-22
* @version: 1.0.0
**/
public class WithoutPrototypePatternDemo {
public static void main(String[] args) {
// 手头有这么一个对象,需要进行拷贝
Product product = new Product("测试产品", new Component("测试组件"));
// 手动来拷贝
Product copyProduct = new Product(product.getName(), product.getComponent());
System.out.println(copyProduct);
// 问题是什么?
// 代码的拷贝逻辑,是每个要拷贝的调用方自己来实现的
// 相同的拷贝逻辑会分散在很多不同的地方,如果拷贝逻辑改变了,多个调用的地方都要修改代码
// 可维护性、可扩展性,很差
}
public static class Component {
private String name;
public Component(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Component [name=" + name + "]";
}
}
public static class Product {
private String name;
private Component component;
public Product(String name, Component component) {
super();
this.name = name;
this.component = component;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Component getComponent() {
return component;
}
public void setComponent(Component component) {
this.component = component;
}
@Override
public String toString() {
return "Product [name=" + name + ", component=" + component + "]";
}
}
}
设计模式
package wang.jinggo.basics.zhss.prototype;
/**
* @author: wangyj
* @create: 2021-10-22
* @version: 1.0.0
**/
public class PrototypePatternDemo {
public static void main(String[] args) {
try {
Product product = new Product("测试产品", new Component("测试组件"));
Product copyProduct = (Product) product.clone();
System.out.println(copyProduct);
} catch (Exception e) {
e.printStackTrace();
}
// 原型模式,就是在要拷贝的类里实现一个clone()方法,自己拷贝自己
// 拷贝的时候,就两个概念,浅拷贝,深拷贝
// 很多地方要克隆这个对象,不要自己维护克隆的逻辑,即使克隆逻辑修改了,只要在clone()方法里面修改
}
public static class Component {
private String name;
public Component(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Component [name=" + name + "]";
}
@Override
protected Object clone() throws CloneNotSupportedException {
return new Component(getName());
}
}
public static class Product {
private String name;
private Component component;
public Product(String name, Component component) {
super();
this.name = name;
this.component = component;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Component getComponent() {
return component;
}
public void setComponent(Component component) {
this.component = component;
}
@Override
public String toString() {
return "Product [name=" + name + ", component=" + component + "]";
}
@Override
protected Object clone() throws CloneNotSupportedException {
// 浅拷贝,就是我们现在的一个实现
// 就是仅仅简单的对当前所有的变量进行一个拷贝
// return new Product(getName(), getComponent());
// 深考别,递归对自己引用的对象也进行拷贝
return new Product(getName(), (Component)getComponent().clone());
}
}
}