1、引入
prototype,中文译为原型、雏形,在 百度百科 中的解释为原来的类型或模型。
而在设计模式中的Prototype模式,就和上文中的原型释意所言,能够通过原型的实例来复制生成新的实例。一般来说,在以下情况中可以使用Prototype模式:
- 要处理的对象繁多,难以将它们整理到同一个类中。
- 对象生成的过程复杂,难以根据类生成实例。
- 在想解耦框架和生成的实例时,不想通过指定类名来生成实例,可以先"注册"一个"原型",之后通过复制该"原型"生成实例。
2、示例
2.1、复制功能接口
对能够实现复制功能的类提供了统一接口进行规范
public interface Product extends Cloneable{
public abstract void use(String s);
public abstract Product createClone();
}
2.2、接口实现
实现1:
public class MessageBox implements Product {
private char decoChar;
public MessageBox(char c) {
decoChar=c;
}
@Override
public void use(String s) {
int len=s.length();
for (int i = 0; i < len+4; i++) {
System.out.print(decoChar);
}
System.out.println();
System.out.println(decoChar+" "+s+" "+decoChar);
for (int i = 0; i < len+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;
}
}
实现2:
public class UnderlinePen implements Product {
private char ulChar;
public UnderlinePen(char c) {
ulChar=c;
}
@Override
public void use(String s) {
int len=s.length();
System.out.println("""+s+""");
System.out.print(" ");
for (int i = 0; i < len; 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;
}
}
2.3、注册中心
在注册中心中提供对对象的登记注册功能,注册后即可通过对象名从注册中心复制实例。
public class Manager {
private HashMap<String,Product> showcase=new HashMap<String,Product>();
public void register(String name, Product proto) {
showcase.put(name, proto);
}
public Product create(String protoName) {
Product product = showcase.get(protoName);
return product.createClone();
}
}
2.4、测试
编写以下测试类:
public class Main {
public static void main(String[] args) {
Manager manager = new Manager();
//创建实例
UnderlinePen upen = new UnderlinePen('#');
MessageBox mbox = new MessageBox('*');
MessageBox sbox = new MessageBox('/');
//登记注册
manager.register("upen", upen);
manager.register("mbox", mbox);
manager.register("sbox", sbox);
//复制生成
Product product1 = manager.create("upen");
Product product2 = manager.create("mbox");
Product product3 = manager.create("sbox");
//测试
product1.use("Hello World");
product2.use("Hello World");
product3.use("Hello World");
}
}
运行结果:
3、tips
- 我们参照示例中的注册中心提供的登记与复制功能,回看1中对Prototype应用场景的阐述,或许能有更深的理解。
- 如在广泛使用的spring框架中,便提供了根据名称注入。这样做的好处是当我们要更换组件时,不必修改源代码中原来的类,只需要再创建一个新类实现共同接口,在新类上提供权限功能,再向注册中心注册即可,大大减少了代码修改量,降低耦合性。
@Autowired
@Qualifier("targetName")