原型模式
在生活中,我们可能会经常遇到这样的情况,比如说我们需要某个软件的安装包,正常的操作是我们会去网上下载,但是这样比较费时费力,比如说找的过程会很浪费时间,还会受网速影响,最别好的办法是直接去别人那拷贝一份,效率高。在java开发中,也存在这种问题,例如创建一个对象如果需要很多步骤,如果每次使用都需要这样去创建的话会很没效率,因此java提供了专门的克隆接口使对象也可以以一个原型对象为基础进行克隆,从而提高效率,这就是原型模式。
原型模式的优点:
- Java 自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
- 可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。
原型模式的缺点:
- 需要为每一个类都配置一个 clone 方法
- clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。
- 当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深克隆、浅克隆需要运用得当。
原型模式包含以下主要角色。
-
抽象原型类:规定了具体原型对象必须实现的接口。
-
具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
-
访问类:使用具体原型类中的 clone() 方法来复制新的对象。
原型模式的克隆分为浅克隆和深克隆。
- 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
- 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
实例,浅克隆一个手机对象
public class Phone implements Cloneable{
String color;
String size;
Date date;
public Phone() {
}
public Phone(String color, String size, Date date) {
this.color = color;
this.size = size;
this.date = date;
}
public Object clone() throws CloneNotSupportedException {
Object object = super.clone();
return object; }
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
@Override
public String toString() {
return "Phone{" +
"color='" + color + '\'' +
", size='" + size + '\'' +
", date=" + date +
'}';
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException, ParseException {
Phone phone = new Phone();
Date date = new Date();
phone.setColor("red");
phone.setDate(date);
Phone phone1 = (Phone) phone.clone();
phone1.setColor("green");
date.setTime(6326);
System.out.println(phone.toString());
System.out.println(phone1.toString());
}
}
结果
修改clone()方法,使其变为深克隆
public class Phone implements Cloneable{
String color;
String size;
Date date;
public Phone() {
}
public Phone(String color, String size, Date date) {
this.color = color;
this.size = size;
this.date = date;
}
public Object clone() throws CloneNotSupportedException {
Object object = super.clone();
Phone phone = (Phone) object;
phone.date = (Date) this.date.clone();
return object; }
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
@Override
public String toString() {
return "Phone{" +
"color='" + color + '\'' +
", size='" + size + '\'' +
", date=" + date +
'}';
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException, ParseException {
Phone phone = new Phone();
Date date = new Date();
phone.setColor("red");
phone.setDate(date);
Phone phone1 = (Phone) phone.clone();
phone1.setColor("green");
date.setTime(6326);
System.out.println(phone.toString());
System.out.println(phone1.toString());
}
}