title: Prototype模式
tag: 笔记 设计模式
Prototype模式
**原型模式(Prototype Pattern)**是用于创建重复的对象,同时又能保证性能。
在Java中我们可以使用使用new关键字获取实例时,是需要指定类名的。但在一些时候我们需要不指定类名来生成实例:
- 对象种类繁多,难以整合到一个类中
- 难以根据类生成实例
- 解耦框架和生成的实例
示例程序
该示例程序是将字符串放入方框中显示处或者是加上下划线显示。该程序由两部分组成:
- framework
Product
:能够被Manager
管理的类的抽象类,必须继承Cloneable
接口。Manager
:负责管理实例的注册和生成
MassageBox
:Product
的具体实现类,将字符串放入方框显示。UnderlinePen
:Product
的具体实现类,将字符串加上下划线显示。
Product接口
public interface Product extends Cloneable {
void use(String s);
Product createClone();
}
需要使用原型模式生成的类都需要实现该接口,并实现两个方法:
user
:该方法用于代表实现类的用途的,具体实现交由子类处理。createClone
:返回该类的克隆实例。
Manager类
public class Manager {
private Map<String, Product> showcase = new HashMap<>();
public void register(String name, Product product){
showcase.put(name, product);
}
public Product create(String name){
return showcase.get(name).createClone();
}
}
该类用于保存所有使用Prototype
模式需要的类并获取保存的类的克隆对象:
showcase
:哈希表结构,存储<name,Product>。
register
:可以将实现Product
接口的类保存到showcase
中create
:并调用Product
中的createClone
得到该实例的一个克隆对象。
MassageBox类
public class MassageBox implements Product {
private char borderChar;
public MassageBox(char borderChar) {
this.borderChar = borderChar;
}
@Override
public void use(String s) {
int width = s.getBytes().length;
printLine(width);
System.out.println("*" + s + "*");
printLine(width);
}
@Override
public Product createClone() {
Product product = null;
try {
product = (Product) clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return product;
}
private void printLine(int width){
for (int i = 0; i < width; i++){
System.out.print(borderChar);
}
System.out.println();
}
}
Product的具体实现类,可以将传入的字符串用指定的字符框起来。其中createClone
调用了clone
方法来返回自己的一个克隆对象。
UnderlinePen类
public class UnderlinePen implements Product {
private char underLineChar;
public UnderlinePen(char underLineChar) {
this.underLineChar = underLineChar;
}
@Override
public void use(String s) {
System.out.println(s);
for(int i = 0; i < s.length(); i++){
System.out.print(underLineChar);
}
System.out.println();
}
@Override
public Product createClone() {
Product product = null;
try {
product = (Product) clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return product;
}
}
Product的具体实现类,可以将传入的字符串用指定的字符作为下划线输出。其中createClone
调用了clone
方法来返回自己的一个克隆对象。
测试
public static void main(String[] args) {
//将实例注册到Manager中管理
Manager manager = new Manager();
manager.register("underlinePen", new UnderlinePen('_'));
manager.register("massageBox", new MassageBox('*'));
//获取到clone实例并使用
Product underlinePen = manager.create("underlinePen");
Product massageBox = manager.create("massageBox");
underlinePen.use("Hello, World!");
massageBox.use("Hello, World!");
}
输出结果:
Hello, World!
_____________
*************
*Hello, World!*
*************
Prototype模式中登场的角色
Prototype
(原型)
Product
角色负责定义用于复制现有实例来生成新实例的方法。在示例程序中,由Product
接口扮演此角色。
ConcretePrototype
(具体的原型)
ConcretePrototype
角色负责实现复制现有实例并生成新实例的方法。在示例程序中,由MessageBox
类和UnderlinePen
类扮演此角色。
Client
(使用者)
Client角色负责使用复制实例的方法生成新的实例。在示例程序中,由Manager
类扮演此角色。
相关的设计模式
Flyweight
模式
使用Prototype
模式可以生成一个与当前实例的状态完全相同的实例。而使用Flyweight
模式可以在不同的地方使用同一个实例。
Memento
模式
使用Prototype
模式可以生成一个与当前实例的状态完全相同的实例。而使用Memento
模式可以保存当前实例的状态,以实现快照和撤销功能。
Composite
模式以及Decorato
经常使用Composite
模式和Decorator
模式时,需要能够动态地创建复杂结构的实例。这时可以使用Prototype
模式,以帮助我们方便地生成实例。
Command
模式
想要复制Command
模式中出现的命令时,可以使用Prototype
模式。
mento`模式可以保存当前实例的状态,以实现快照和撤销功能。
Composite
模式以及Decorato
经常使用Composite
模式和Decorator
模式时,需要能够动态地创建复杂结构的实例。这时可以使用Prototype
模式,以帮助我们方便地生成实例。
Command
模式
想要复制Command
模式中出现的命令时,可以使用Prototype
模式。