原型模式
概述
在Java中,我们通常使用类名来创建一个对象,但是在开发过程中,有时候也会有”在不指定类名的前提下生成实例“的需求。原型模式可以满足这种需求,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
示例程序
在示例程序中,我们实现以下需求
调用方法生成指定格式的字符串,如下
调用MessageBox
**********
* string *
**********
调用UnderlinePen
string
~~~~~~
UML类图
名字 | 说明 |
---|---|
Product | 声明了抽象方法use和createClone的接口 |
Manager | 调用createClone方法复制实例的类 |
MessageBox | 将字符串放入方框中,实现了Product |
UnderlinePen | 给字符串加上下划线,实现了Product |
代码实现
Product
public interface Product extends Cloneable{
void use(String s);
Product createClone();
}
Manager
public class Manager {
private HashMap showCase = new HashMap();
public void register(String name,Product product){
showCase.put(name,product);
}
public Product create(String name){
Product product = (Product) showCase.get(name);
return product.createClone();
}
}
MessageBox
public class MessageBox implements Product {
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 + 4; i++) {
System.out.print(decochar);
}
System.out.println();
System.out.println(decochar + " " + s + " " + decochar);
for (int i = 0; i < length + 4; i++) {
System.out.print(decochar);
}
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 {
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.print(ulchar);
}
System.out.println(" ");
}
@Override
public Product createClone() {
Product p = null;
try {
p = (Product) clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
}
test
@SpringBootTest
class Practice700ApplicationTests {
@Test
void contextLoads() {
Manager manager = new Manager();
manager.register("strong message",new UnderlinePen('~'));
manager.register("warn box",new MessageBox('*'));
manager.register("slash box",new MessageBox('/'));
Product strong_message = manager.create("strong message");
strong_message.use("yellowstar");
Product warn_box = manager.create("warn box");
warn_box.use("yellowstar");
Product slash_box = manager.create("slash box");
slash_box.use("yellowstar");
}
}
//结果
"yellowstar"
~~~~~~~~~~
**************
* yellowstar *
**************
//
/ yellowstar /
//
原型模式中登场的角色
-
Prototype(原型)
Prototype角色负责定义用于复制现有实例来生成新实例的方法,在示例中,Product扮演该角色
-
ConcretePrototype(具体的原型)
ConcretePrototype角色负责实现复制现有实例并生成新实例的方法的类,在示例中MessageBox、UnderlinePen扮演这一角色
UML类图
习题
在示例程序中,我们发现MessageBox、UnderlinePen的createClone实现方法完全一样,从管理的角度来讲,多个地方出现完全一样的方法不太好,因此我们想让这两个类共用该方法,该如何实现?
将product接口改为抽象类
public abstract class ProductClazz implements Cloneable{
public abstract void use(String s);
public ProductClazz createClone(){
ProductClazz p = null;
try {
p = (ProductClazz) clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
}