通过复制生成实例
new xxx()
通常情况,使用new来生成类的实例,指定类名。
需求:在 不指定类名的前提下生成实例
1)对象种类繁多,无法将它们整合到一个类中
2)难以根据类生成实例
3)想解耦框架与生成的实例
生成的实例的框架不依赖具体的类,不能指定类名来生成实例,需要“注册”一个“原型”实例,复制该实例生成新的实例。
示例
功能:将字符串放入方框中显示出来或是加上下划线显示。
Product接口和Manager接口属于框架,负责复制实例。 Manager回调用createClone方法,但它不知道复制的类是谁。实现了Product接口的类,调用createClone就能复制新的实例。
MessageBox类和UnderlinePen类是两个实现了Product接口的类。事先,需要将这两个类“注册”到Manager类中,就可以随时复制新的实例。
Product接口
/**
* 复制功能接口. 继承了Cloneable 才能在后续调用clone 本身并不实现clone方法
* use方法是用于 使用 的方法。 使用具体由子类实现
* createClone 方法用于复制实例的方法
*/
public interface Product extends Cloneable {
public abstract void use(String s);
public abstract Product createClone();
}
Manager接口
/**
* Manager类 使用Product接口实现复制
* showcase 保存实例 名字 和 实例 对应关系 使用了HashMap
* register方法, 接收一组 名字-Product接口 注册 showcase 这里的proto是需要实现Product接口的类的实例
*
* 这里Product 和 Manager 并没有出现 MessageBox和UnderlinePen 类的名字 因此可以单独修改
* 解耦了相关的类 一旦用到了类 就是耦合了 Manager这里只用了Product这个代名词 没有具体的类名
*/
public class Manager {
private HashMap showcase = new HashMap();
public void register(String name, Product proto){
showcase.put(name,proto);
}
public Product create(String protoName){
Product p = (Product) showcase.get(protoName);
return p.createClone();
}
}
MessageBox类
/**
* 实现Product接口
* 定义了decochar 用于装饰字符串的字符信息
* use方法使用 上述字符 包裹字符串信息返回
*
* createClone方法用于复制自己 复制时,原来实例的字段的值也会复制到新的实例中,能调用clone的前提是实现了Cloneable接口
* 没有实现会抛出异常,Product继承了这类 所以可以调用,但是 Cloneable接口没有定义方法
*
* 只有类自己能够调用clone方法,当其他类要求复制实例是偶,必须先调用 createClone这样的方法,然后在方法内调用clone()
*/
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接口
/**
* 该类ulchar字段是用来保存装饰下划线样式的字符
* use方法 将字符串双引号放置显示 再在字符串下添加下划线
*/
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;
}
}
Main类
public class Main {
public static void main(String[] args) {
Manager manager = new Manager();
UnderlinePen upen = new UnderlinePen('~');
MessageBox mbox = new MessageBox('*');
MessageBox xbox = new MessageBox('/');
manager.register("strong message", upen);
manager.register("warning box", mbox);
manager.register("slash box", xbox);
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.");
}
}
运行结果:
"Hello, world."
~~~~~~~~~~~~~
*****************
* Hello, world. *
*****************
/
/ Hello, world. /
/
Prototype模式
主要解决的是 作为一个组件的形式去复用