原型设计模式
定义
指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
特点
不需要知道任何创建的细节,不调用构造函数
类型:创建型
使用场景
类初始化消耗较多资源
new 产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)
构造函数比较复杂
循环体中生产大量对象时
原型模式优缺点
优点:
原型模式性能比直接new一个对象性能高
简化创建过程
缺点:
必须配备克隆方法
对克隆复杂对象或对克隆出的对象进行复杂改造时,容易引入风险
深拷贝、浅拷贝要运用得当
原型——扩展:深克隆 浅克隆
实例
原型模式通过clone的方式来创建另一个对象,而不是直接调用构造方法。这里就涉及到深克隆与浅克隆的坑。
实例:Pig类需要实现Cloneable接口
public class Pig implements Cloneable {
private String name;
private Date birthday;
public Pig(String name, Date birthday) {
this.name = name;
this.birthday = birthday;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Pig{" +
"name='" + name + '\'' +
", birthday=" + birthday +
'}'+super.toString();
}
}
调用
public class Test {
public static void main(String[] args) {
try {
Date birthday = new Date(0L);
Pig pig = new Pig("佩奇", birthday);
Pig pig1 = (Pig) pig.clone();
System.out.println(pig.toString());
System.out.println(pig1.toString());
pig.getBirthday().setTime(1200L);
System.out.println(pig.toString());
System.out.println(pig1.toString());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
此时的打印信息:
Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}com.df.designpatterns.prototype.clone.Pig@7f31245a
Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}com.df.designpatterns.prototype.clone.Pig@6d6f6e28
Pig{name='佩奇', birthday=Thu Jan 01 08:00:01 CST 1970}com.df.designpatterns.prototype.clone.Pig@7f31245a
Pig{name='佩奇', birthday=Thu Jan 01 08:00:01 CST 1970}com.df.designpatterns.prototype.clone.Pig@6d6f6e28
此时可以发现在只修改pig的birthday的时间的时候,pig1的时间也发生了变化。这样就出现了问题,也就是我们说的bug,不难发现要修改这个bug,需要对pig类的clone方法进行修改,如下:
@Override
protected Object clone() throws CloneNotSupportedException {
Pig pig= (Pig) super.clone();
pig.birthday= (Date) pig.birthday.clone();
return pig;
}
即对pig中引用对象birthday也进行拷贝
修改代码之后打印如下:
Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}com.df.designpatterns.prototype.clone.Pig@7f31245a
Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}com.df.designpatterns.prototype.clone.Pig@6d6f6e28
Pig{name='佩奇', birthday=Thu Jan 01 08:00:01 CST 1970}com.df.designpatterns.prototype.clone.Pig@7f31245a
Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}com.df.designpatterns.prototype.clone.Pig@6d6f6e28
小结
原型模式使用的时候需要小心深拷贝与浅拷贝带来的bug
转载:https://blog.csdn.net/danfengw/article/details/95110266
查看评论