原型模式是指实例指定创建对象的种类,并且通过复制这些原型创建新的对象。
原型模式的使用场景:
(1):类初始化消耗资源多。
(2):使用new 生成一个对象需要非常繁琐的过程(数据准备,访问权限等)。
(3):构造函数比较复杂。
(4):在循环体中产生大量对象。
举一个我们日常工作中的例子,比如每周都要写周报,每一周的周报除了内容不一样其他都是一样的,比如 姓名,职位,部门等
下面我们来实现以下:
首先创建一个周报类
public class WeeklyLog implements Cloneable , Serializable {
private static final long serialVersionUID = 1493336210318121293L;
/**
* 姓名
*/
private String name;
/**
* 日期
*/
private Date date;
/**
* 内容
*/
private String content;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
然后写第一周的周报:
WeeklyLog weeklyLog1 = new WeeklyLog();
weeklyLog1.setName("张三");
weeklyLog1.setDate(new Date());
weeklyLog1.setContent("写代码");
写第二周的周报时就可以复制第一周的周报然后来做修改:可以使用浅克隆
向WeeklyLog中添加克隆方法
@Override
public WeeklyLog clone() throws CloneNotSupportedException {
return (WeeklyLog) super.clone();
}
WeeklyLog weeklyLog2 = weeklyLog1.clone();
System.out.println("浅克隆两次的周报时间引用对象是否一样:" + (weeklyLog1.getDate() == weeklyLog2.getDate()));
System.out.println("浅克隆两次的周报引用对象是否一样:" + (weeklyLog1 == weeklyLog2));
运行结果:
浅克隆两次的周报时间引用对象是否一样:true
浅克隆两次的周报引用对象是否一样:false
测试代码来看浅克隆出来的对象是不同的但是对象内部引用的对象还是同一个内存地址,如果有特殊业务需要对象内部的对象引用也不一样就可以使用深克隆
需要向WeeklyLog对象中加入深克隆方法
public WeeklyLog deepClone() throws IOException, ClassNotFoundException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(this);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
return (WeeklyLog) objectInputStream.readObject();
}
测试代码
// 深克隆 克隆得到的对象地址不一样,并且对象内部引用的其他对象也不是同一个内存地址
WeeklyLog weeklyLog3 = weeklyLog1.deepClone();
System.out.println("深克隆两次的周报时间引用对象是否一样:" + (weeklyLog1.getDate() == weeklyLog3.getDate()));
System.out.println("深克隆两次的周报引用对象是否一样:" + (weeklyLog1 == weeklyLog3));
运行结果:
深克隆两次的周报时间引用对象是否一样:false
深克隆两次的周报引用对象是否一样:false
这样就可以得到一个由内而外都不一样的对象了,这就是原型模式
优点:
1. 简化创建对象流程
2.克隆比直接创建对象性能要高
缺点:
1.需要配备克隆方法
2.深、浅克隆需要使用得当