背景
原型(prototype)模式可以在不指定类名的前提下生成实例
以下情况不能根据类来生成实例,要根据现有的实例来生成实例
- 对象种类繁多,无法将它们整合到一个类中
需要处理的对象过多,如果将它们分别作为一个类,必须要编写很多歌类文件
- 难以根据类生成实例时
生成实例的过程太过复杂,很难根据类来生成实例
- 想解耦框架与生成的实例时
要想让生成实例的框架不依赖于具体的类,这时,不能指定类名来生成实例,而要先“注册”一个原型实例,然后通过复制来生成该新的实例
登场角色
Prototype 原型
负责定义用于复制现有的实例来生成新实例的方法
ConcretePrototype 具体的原型
ConcretePrototype 负责实现 用于复制现有的实例来生成新实例的方法
Client 使用者
Client 角色负责使用复制实例的方法生成新的实例
示例代码
示例代码为以不同的形式来显示字符串
Product
/**
* 产品的接口
*/
public interface Product {
void use(String s);
Product createClone();
}
MessageBox
public class MessageBox implements Product, Cloneable {
private char decochar;
public MessageBox(char decochar) {
this.decochar = decochar;
}
@Override
public void use(String s) {
int length = s.getBytes().length;
for (int i = 0; i < length; i++) {
System.out.print(decochar);
}
System.out.println();
System.out.println(decochar + " " + s + " " + decochar);
for (int i = 0; i < length + 4; i++) {
System.out.println(decochar);
}
Object o = new Object();
System.out.println();
}
@Override
public Product createClone() {
Product p = null;
try {
p = (Product) clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
}
UnderlinePen
public class UnderlinePen implements Product, Cloneable {
private char ulchar;
public UnderlinePen(char ulchar) {
this.ulchar = ulchar;
}
@Override
public void use(String s) {
int length = s.getBytes().length;
System.out.println(""" + s + """);
System.out.print(" ");
for (int i = 0; i < length; i++) {
System.out.println(ulchar);
}
System.out.println("");
}
@Override
public Product createClone() {
Product p = null;
try {
p = (Product) clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
}
Manager
public class Manager {
private HashMap<String, Product> hashMap = new HashMap<>();
public void register(String name, Product product) {
hashMap.put(name, product);
}
public Product create(String name) {
Product product = hashMap.get(name);
return product.createClone();
}
}
Main
public class Main {
public static void main(String[] args) {
Manager manager = new Manager();
UnderlinePen underlinePen = new UnderlinePen('~');
MessageBox sbox = new MessageBox('*');
MessageBox mbox = new MessageBox('/');
// 注册
manager.register("strong message", underlinePen);
manager.register("warning box", sbox);
manager.register("slash box", mbox);
// 生成
Product p1 = manager.create("strong message");
p1.use("hello world");
Product p2 = manager.create("warning box");
p2.use("hello world");
Product p3 = manager.create("slash box");
p3.use("hello world");
}
}
类图
功能分析
- 当类的数量十分庞大时,源程序的管理也会变得十分困难,而原型模式可以将这些类集中在一起解决;
- 将框架从类名的束缚中解脱出来,因为一旦在代码中出现要使用的类的名字,就无法与该类分离开来,也无法实现复用;
- clone 方法实现的是浅复制,即字段对字段的复制;