原型模式
内容:用原型的实例指定创建对象的种类,并且通过复制这些对象原型来创建新的对象。
结构:
抽象原型:其是一个接口,负责定义对象复制自身的方法。
具体原型:实现了抽象原型接口的子类,并提供了具体复制自身的方法。
UML类图:
优点:
原型模式对于创建新的对象过于复杂时可以提高创建新对象的效率,可以在运行时动态的保存当前的对象,也可以动态的增加和删除原型的复制品。
适用情境:
当对象的创建过程需要独立于其构造过程时,程序需要从现有的对象出发,得到若干状态相同但可以独立变化的新对象时。
在Java中系统提供了clone()方法,它是Object类中的protected权限的方法,该方法可用于复制当前对象,而用户自定义的类不会与Object类在同一个包(java.lang)中,虽然所有的类都是Object的子类,但也不能直接使用其clone()方法。因此要想使用clone()方法,用户自定义的类可以重写Object类的clone()方法,然后在方法体中通过super关键字来调用Object类的clone()方法,当对象调用Object类中的方法时,JVM会逐个复制该对象的成员变量,然后创建一个新的对象返回,JVM要去调用clone()方法的对象必须实现Cloneable接口,该接口只是起标识作用,接口中没有任何方法。另外,需要注意的是,若当前对象中的成员变量也是一个对象,调用clone()方法只会复制该对象的引用,并没有复制该对象所拥有的变量,也就是未能实现完全意义上的复制。因此,若需要完全复制,则需要对当前对象中的成员变量对象也进行复制,这样才能实现完全复制(深度复制)。
使用实例:
//原型
public interface Prototype {
public Object cloneSelf() throws CloneNotSupportedException;
}
public class Rectangle implements Cloneable {
private double width;
private double longth;
public Rectangle(double width, double longth){
this.longth = longth;
this.width = width;
}
public double getAera(){
return this.longth * this.width;
}
public Object clone() throws CloneNotSupportedException{
Object object = super.clone();
return object;
}
public void setWidth(double width) {
this.width = width;
}
public void setLongth(double longth) {
this.longth = longth;
}
}
//包含了引用型成员变量的具体原型
public class Cube implements Cloneable, Prototype {
private Rectangle rectangle;
private double height;
public Cube(Rectangle rectangle, double height) {
this.rectangle = rectangle;
this.height = height;
}
public double getVolum(){
return this.rectangle.getAera() * this.height;
}
@Override
public Object cloneSelf() throws CloneNotSupportedException {
// TODO Auto-generated method stub
Cube object = (Cube)super.clone();
object.rectangle = (Rectangle)rectangle.clone();
return object;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Rectangle rectangle = new Rectangle(1.0, 2.0);
Cube cube = new Cube(rectangle, 3.0);
System.out.println("原型:"+cube.getVolum());
try {
Cube cubecopy1 = (Cube)cube.cloneSelf();
System.out.println("复制份1:"+cubecopy1.getVolum());
rectangle.setLongth(10.0);//改动成员变量的属性值
Cube cubecopy2 = (Cube)cube.cloneSelf();
System.out.println("复制份2:"+cubecopy2.getVolum());
System.out.println("复制份1:"+cubecopy1.getVolum());//复制份1没有受到影响
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
原型模式的核心是通过当前对象以复制的方式产生新的对象。