一. 定义 用原型实例指定创建对象的种类、 并且通过拷贝这些原型创建新的对象。
二. 结构
三. 参与者
Prototype : 克隆自身的接口(如代码实现中的FruitPrototype)
PrototypeTool : 管理Prototype的工具类, 存储原型复制自身到数据接口(如FruitTool)
ConcretePrototype : 实现一个克隆自身的操作(如ConcteteFruitPrototype)
Client : 测试类
四. 适用性
-- 多用于创建复杂的或者耗时的实例,因为这种情况下,复制一个已经存在的实例使程序运行更高效
-- 创建值相等,只是命名不一样的同类数据
-- 实例化的类是在运行时加载, 例如动态加载
-- 避免创建一个与产品类层次平行的工厂类层次(即避免像工厂方法一样, 可能会创建太多子类)
五. 代码实现
原型接口: 对外提供获取原型拷贝的入口
package com.wenniuwuren.prototype;
/**
* 原型接口
* @author wenniuwuren
*
*/
public interface FruitPrototype{
public abstract FruitPrototype cloneNew() throws CloneNotSupportedException;
}
package com.wenniuwuren.prototype;
/**
* 原型具体实现
* @author wenniuwuren
*
*/
public class ConcteteFruitPrototype implements FruitPrototype, Cloneable{
private String size;
private String color;
public ConcteteFruitPrototype(String size, String color) {
this.size = size;
this.color = color;
}
// 克隆
public FruitPrototype cloneNew() throws CloneNotSupportedException {
return (FruitPrototype) super.clone();
}
// 方便打印
public void display(String colorname) {
System.out.println(colorname+"的大小是: "+size+" 颜色是:"+color);
}
}
package com.wenniuwuren.prototype;
import java.util.HashMap;
/**
* 原型管理类
* @author wenniuwuren
*
*/
public class FruitTool {
private HashMap<String, FruitPrototype> fruits = new HashMap<String, FruitPrototype>();
public void put(String key, FruitPrototype fruitPrototype) {
fruits.put(key, fruitPrototype);
}
public FruitPrototype get(String key) {
return fruits.get(key);
}
}
测试类:
package com.wenniuwuren.prototype;
public class Client {
public static void main(String[] args) throws CloneNotSupportedException {
FruitTool fruitTool = new FruitTool();
// 初始化水果的大小和颜色
fruitTool.put("Apple", new ConcteteFruitPrototype("Middle", "Green"));
fruitTool.put("Watermelon", new ConcteteFruitPrototype("Large", "Red"));
fruitTool.put("Lemon", new ConcteteFruitPrototype("Small", "Yellow"));
String fruitName = "Apple";
ConcteteFruitPrototype concteteFruitPrototype = (ConcteteFruitPrototype) fruitTool
.get(fruitName).cloneNew();
concteteFruitPrototype.display(fruitName);
fruitName = "Lemon";
concteteFruitPrototype = (ConcteteFruitPrototype) fruitTool.get(
fruitName).cloneNew();
concteteFruitPrototype.display(fruitName);
}
}
运行结果:
Apple的大小是: Middle 颜色是:Green
Lemon的大小是: Small 颜色是:Yellow
以上代码是利用JDK自带的clone()实现Prototype模式, 这里面的clone()使用的是浅克隆。
浅克隆 : 只负责克隆按值传递的数据(比如基本数据类型、String类型),而不复制它所引用的对象,既所有的对其他对象的引用都仍然指向原来的对象(如自定义类LeafReferrence, 在clone()后LeafReferrence引用只有唯一的一份,改变复制前的索引和改变复制后的索引所引起的都是全局的改变, 即对象引用不被复制, JVM内存模型中仅有一份)。
深克隆 : 则把前克隆所没复制的引用复制了一份, 跟基本数据类型和String一样都是新的一份, 复制前后的是独立的。(天色已晚, 深克隆稍后补上)
参考资料:
Wikipedia : 原型模式
《设计模式 : 可复用面向对象软件的基础》