原型模式
原型模式
概述
原型模式是一种创建型设计模式, 使你能够复制已有对象, 而又无需使代码依赖它们所属的类。
场景
如果有一个对象,希望生成与其完全相同的一个复制品。最直接的步骤就是创建一个相同的类,然后遍历所有成员变量赋值到新对象中。
问题
有些对象可能拥有私有的成员变量在本身之外不可见,同时还有一个问题:必须知道所属的类才能创建复制品,所以代码必须依赖该类,但于此同时你可能仅知道这个对象所实现的接口,但还并不知道所属具体类。
解决方法
让对象实现克隆的功能。调用这个克隆的功能会生成一个完全一样的对象。
代码实例
// 原型类
public abstract class Shape implements Cloneable {
public int positionX;
public int positionY;
private Ref ref;
public Ref getRef() {
return ref;
}
// 测试深浅拷贝
public void setRef(Ref ref) {
this.ref = ref;
}
public Shape(int positionX, int positionY) {
this.positionX = positionX;
this.positionY = positionY;
}
public int getPositionX() {
return positionX;
}
public void setPositionX(int positionX) {
this.positionX = positionX;
}
public int getPositionY() {
return positionY;
}
public void setPositionY(int positionY) {
this.positionY = positionY;
}
@Override
protected Shape clone() throws CloneNotSupportedException {
System.out.println("原型克隆成功");
return (Shape) super.clone();
}
}
public class Rectangle extends Shape {
public Rectangle(int positionX, int positionY, int width, int length) {
super(positionX, positionY);
this.width = width;
this.length = length;
}
public Rectangle(int positionX, int positionY) {
super(positionX, positionY);
}
private int width;
private int length;
public void setWidth(int width) {
this.width = width;
}
public void setLength(int length) {
this.length = length;
}
@Override
public String toString() {
return "Rectangle{" +
"width=" + width +
", length=" + length +
", positionX=" + positionX +
", positionY=" + positionY +
'}';
}
}
// 测试引用类
public class Ref {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
// 测试类
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
// 在x=4,y=5 坐标下创建一个长为4,宽为2的矩形
Rectangle rectangle = new Rectangle(4, 5, 4, 2);
Ref ref = new Ref();
ref.setName("jack");
rectangle.setRef(ref);
// 复制一下
Shape rectangleClone = rectangle.clone();
// 查看一下位置和大小
System.out.println(rectangleClone);
// 查看是否是同一个对象
System.out.println(rectangle == rectangleClone);
// 验证clone是浅克隆:结果是浅拷贝
rectangleClone.getRef().setName("rose");
System.out.println(rectangle.getRef().getName());
}
}
总结
- clone方法是浅拷贝,如果要实现深拷贝需要用流来处理
- 克隆包含循环引用的对象很麻烦
- 克隆对象要实现Cloneable接口