3. 原型模式(Prototype Pattern)
原型模式,顾名思义,就是有一个原型,可以根据这个原型来创建其他的对象,当要创建一些列相似的对象时,使用原型来克隆总比直接创建一个新的对象要来的直接。
还是举个例子吧,比如说一个配钥匙的过程,不过使用一个非常笨的方法。
首先是一个钥匙的类:
其次是一个配钥匙的机器:
最后是测试的客户端:
上边的三个类模拟了一个配钥匙的过程,对一个Key进行了复制,但是,严格的说,上边的实现挺麻烦的,并且没有什么通用性,每次都要了解要被复制的对象的内部结构,其实就是把老对象和新对象间的状态复制过程封装了一下。java有很好的实现方式,就是java本身提供的#clone()方法。
比如上边的这个配钥匙的例子,用#clone()方法的实现如下。在这里,我修改了钥匙这个类中表示形状的成员,把它独立出来作为一个类Shape。
然后是Key
最后是客户端:
执行Client之后,控制台会显示出 "1",说明同之前的那个Key的状态时相同的。
不过我们还可以做下面的一个实验,把Client做一些修改:
程序会在控制台打印 "0";
修改了克隆后的新的钥匙的State,不过原来的钥匙的State也发生了变化。也就是说前后两个钥匙的状态发生了联系,这个与原型模式是相违背的。
上述的那个Clone()方法在java中叫"影子克隆",对所有状态进行的克隆,叫做"深度克隆"。我们来继续改写上边的例子。
这次的结果就是"1"了。
最后,给出原型模式的类图:
[img]http://zddava.iteye.com/upload/attachment/75986/d59785be-afbe-31e5-9007-7946d1cf15c5.jpg[/img]
原型模式,顾名思义,就是有一个原型,可以根据这个原型来创建其他的对象,当要创建一些列相似的对象时,使用原型来克隆总比直接创建一个新的对象要来的直接。
还是举个例子吧,比如说一个配钥匙的过程,不过使用一个非常笨的方法。
首先是一个钥匙的类:
public class Key {
// 使用一个整形变量来代表钥匙的形状吧
private int shape = 0;
public int getShape() {
return shape;
}
public void setShape(int shape) {
this.shape = shape;
}
}
其次是一个配钥匙的机器:
public class KeyCopier {
public Key copy(Key key){
Key newKey = new Key();
newKey.setShape(key.getShape());
return newKey;
}
}
最后是测试的客户端:
public class Client {
public static void main(String[] args) {
Key key = new Key();
key.setShape(1);
KeyCopier copier = new KeyCopier();
Key newKey = copier.copy(key);
}
}
上边的三个类模拟了一个配钥匙的过程,对一个Key进行了复制,但是,严格的说,上边的实现挺麻烦的,并且没有什么通用性,每次都要了解要被复制的对象的内部结构,其实就是把老对象和新对象间的状态复制过程封装了一下。java有很好的实现方式,就是java本身提供的#clone()方法。
比如上边的这个配钥匙的例子,用#clone()方法的实现如下。在这里,我修改了钥匙这个类中表示形状的成员,把它独立出来作为一个类Shape。
public class Shape {
private int state = 0;
public Shape(int state) {
this.state = state;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
}
然后是Key
public class Key implements Cloneable {
// 使用一个整形变量来代表钥匙的形状吧
private Shape shape = null;
public Key(Shape shape){
this.shape = shape;
}
public Shape getShape() {
return shape;
}
public void setShape(Shape shape) {
this.shape = shape;
}
public Object clone() {
Key obj = null;
try {
obj = (Key) super.clone();
} catch (CloneNotSupportedException e) {
}
return obj;
}
}
最后是客户端:
public class Client {
public static void main(String[] args) {
Shape shape = new Shape(1);
Key key = new Key(shape);
// 克隆了钥匙
Key newKey = (Key) key.clone();
System.out.println(newKey.getShape().getState());
}
}
执行Client之后,控制台会显示出 "1",说明同之前的那个Key的状态时相同的。
不过我们还可以做下面的一个实验,把Client做一些修改:
public class Client {
public static void main(String[] args) {
Shape shape = new Shape(1);
Key key = new Key(shape);
// 克隆了钥匙
Key newKey = (Key) key.clone();
Shape newShape = newKey.getShape();
newShape.setState(0);
System.out.println(key.getShape().getState());
}
}
程序会在控制台打印 "0";
修改了克隆后的新的钥匙的State,不过原来的钥匙的State也发生了变化。也就是说前后两个钥匙的状态发生了联系,这个与原型模式是相违背的。
上述的那个Clone()方法在java中叫"影子克隆",对所有状态进行的克隆,叫做"深度克隆"。我们来继续改写上边的例子。
public class Shape implements Cloneable {
private int state = 0;
public Shape(int state) {
this.state = state;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
//实现Clone()方法
public Object clone() {
Shape obj = null;
try {
obj = (Shape) super.clone();
} catch (CloneNotSupportedException e) {
}
return obj;
}
}
public class Key implements Cloneable {
// 使用一个整形变量来代表钥匙的形状吧
private Shape shape = null;
public Key(Shape shape) {
this.shape = shape;
}
public Shape getShape() {
return shape;
}
public void setShape(Shape shape) {
this.shape = shape;
}
public Object clone() {
Key obj = null;
try {
obj = (Key) super.clone();
} catch (CloneNotSupportedException e) {
}
// 加入了Shape的Clone
obj.setShape((Shape) shape.clone());
return obj;
}
}
public class Client {
public static void main(String[] args) {
Shape shape = new Shape(1);
Key key = new Key(shape);
// 克隆了钥匙
Key newKey = (Key) key.clone();
Shape newShape = newKey.getShape();
newShape.setState(0);
System.out.println(key.getShape().getState());
}
}
这次的结果就是"1"了。
最后,给出原型模式的类图:
[img]http://zddava.iteye.com/upload/attachment/75986/d59785be-afbe-31e5-9007-7946d1cf15c5.jpg[/img]