您的位置:首页 > 其它

设计模式学习笔记(十三:原型模式)

2016-11-04 21:47 447 查看

1.1概述

用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。这就是原型模式的定义。

在某些情况下,可能不希望反复使用类的构造方法创建许多对象,而是希望使用该类创建一个对象后,以该对象为原型得到该对象的若干个复制品。也就是说,将一个对象定义为原型对象,要求改原型对象提供一个方法,使该原型对象调用此方法可以复制一个和自己有完全相同状态的同类型对象,即该方法“克隆”原型对象得到一个新对象。原型对象和以它为原型“克隆”出的新对象可以分别独立地变化,也就是说,原型对象改变其状态不会影响到以它为原型“克隆”出的新对象,反之也一样。

例如,通过复制一个已有的Word文档中的文本创建一个新的Word文档后,两个文档中的文本内容可独立地变化互不影响。

原型模式是从一个对象出发得到一个和自己有相同状态的新对象的成熟模式,该模式的关键是将一个对象定义为原型,并为其提供复制自己的方法。

1.2模式的结构

原型模式结构包括两种角色:

(1)抽象原型(Prototype):一个接口,负责定义对象复制自身的方法。

(2)具体原型(ConcretePrototype):实现Prototype接口的类,具体原型实现抽象原型中的方法,以便所创建的对象调用该方法复制自己。

原型模式结构的类图如下图所示:



图一:原型模式结构的类图

1.3原型模式的优点

(1)当创建类的新实例的代价更大时,使用原型模式复制一个已有的实例可以提高创建新实例的效率。

(2)可以动态地保持当前对象的动态。在运行时,可以随时使用对象流保存当前对象的一个复制品。

(3)可以在运行时创建新的对象,而无须创建一系列类和继承结构。

(4)可以动态地添加、删除原型的复制品。

1.4适合使用原型模式的情景

(1)程序需要从一个对象出发,得到若干个和其状态相同,并可独立变化其状态的对象时。

(2)当对象的创建需要独立于它的构造过程和表示时。

(3)一个类创建实例状态不是很多,那么就可以将这个类的一个实例定义为原型,那么通过复制该原型得到新的实例可能比重新使用类的构造方法创建新实例更方便。

1.5原型模式的使用

以下通过一个简单的问题:克隆一个立方体和一个山羊来描述原型模式中所涉及的各个角色,具体如下:

首先看一下本实例构建框架具体类和1.2模式的结构中类图的对应关系,如下图所示:



(1)抽象原型(Prototype)

抽象原型是Prototype接口,该接口的代码如下:

package com.liuzhen.thirteen_prototype;

public interface Prototype {
public Object cloneMe() throws CloneNotSupportedException;
}


(2)具体原型(Concrete Prototype)

具体原型是Cubic类和Goat类。Goat类使用对象序列化来复制对象,Java类库中的绝大多数类都实现了Serializable接口,比如StringBuffer类以及java.awt包中的组件类等。Cubic类和Goat类的代码如下:

Cubic.java

package com.liuzhen.thirteen_prototype;

public class Cubic implements Prototype , Cloneable{
double length , width , height;
Cubic(double a,double b,double c){
length = a;
width = b;
height = c;
}
public Object cloneMe() throws CloneNotSupportedException{
Cubic object = (Cubic) clone();
return object;
}
}


Goat.java

package com.liuzhen.thirteen_prototype;

import java.io.*;

@SuppressWarnings("serial")
public class Goat implements Prototype , Serializable{
StringBuffer color;
public void setColor(StringBuffer c){
color = c;
}
public StringBuffer getColor(){
return color;
}
public Object cloneMe() throws CloneNotSupportedException{
Object object = null;
try{
ByteArrayOutputStream outOne = new ByteArrayOutputStream();
ObjectOutputStream outTwo = new  ObjectOutputStream(outOne);
outTwo.writeObject(this);      //将原型对象写入对象输出流
ByteArrayInputStream inOne = new ByteArrayInputStream(outOne.toByteArray());
ObjectInputStream inTwo = new ObjectInputStream(inOne);
object = inTwo.readObject();   //创建新的对象;原型的复制品
}
catch(Exception event){
System.out.println(event);
}
return object;
}
}


(3)模式的具体使用

通过ThirTeenApplication类来具体实现上述相关类和接口,来实现原型模式的运用,其代码如下:

package com.liuzhen.thirteen_prototype;

public class ThirteenApplication {
public static void main(String[] args){
Cubic cubic = new Cubic(12,20,66);
System.out.println("cubic的长、宽和高:");
System.out.println(cubic.length+","+cubic.width+","+cubic.height);
try{
Cubic cubicCopy = (Cubic) cubic.cloneMe();
System.out.println("cubicCopy的长、宽和高:");
System.out.println(cubicCopy.length+","+cubicCopy.width+","+cubicCopy.height);
}
catch(CloneNotSupportedException exp){

}
Goat goat = new Goat();
goat.setColor(new StringBuffer("白颜色的山羊"));
System.out.println("goat是"+goat.getColor());
try{
Goat goatCopy = (Goat)goat.cloneMe();
System.out.println("goatCopy是"+goatCopy.getColor());
System.out.println("goatCopy将自己的颜色变成黑色");
goatCopy.setColor(new StringBuffer("黑颜色的山羊"));
System.out.println("goat仍然是"+goat.getColor());
System.out.println("goatCopy是"+goatCopy.getColor());
}
catch(CloneNotSupportedException exp){

}
}
}


[b]运行结果:[/b]

cubic的长、宽和高:
12.0,20.0,66.0
cubicCopy的长、宽和高:
12.0,20.0,66.0
goat是白颜色的山羊
goatCopy是白颜色的山羊
goatCopy将自己的颜色变成黑色
goat仍然是白颜色的山羊
goatCopy是黑颜色的山羊


参考资料:

1.Java设计模式/耿祥义,张跃平著.——北京:清华大学出版社,2009.5
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: