文章目录
1. 引言
Prototype原型模式是指根据实例原型、实例模型来生成新的实例。
2. 示例程序
2.1 类和接口一览表
包 | 类名 | 说明 |
---|---|---|
framewrok | Product | 声明抽象方法use和createClone的接口 |
framework | Manager | 调用createClone方法复制实例的类 |
MessageBox | 实现了use和createClone方法,将字符串放入方框中显示 | |
MessageUnderline | 实现了use和createClone方法,将字符串下方添加一串字符显示 | |
Main | 测试程序行为的类 |
2.2 UML图
2.3 Product接口
use定义“使用”的方法。
createClone方法定义用于复制实例的方法。
/**
* 继承Cloneable接口
* @author littlemotor
* @since 8.18
*/
public interface Printer extends Cloneable{
public abstract void print();
}
2.4 Manager类
Manager并没有用到别的具体需要复制的类名,保证了与其他类之间的松耦合。
public class Manager {
private HashMap<String, Printer> printers = new HashMap<>();
public void register(String name, Printer prototype) {
printers.put(name, prototype);
}
public Printer create(String protoname) {
Printer p = (Product) printers.get(protoname);
return p.clone();
}
}
2.5 WhitePrinter类
createClone方法用于复制自己,在进行复制时,原来实例中字段的值也会被复制到新的实例中,之所以能够调用clone方法是因为父类中实现了Cloneable接口。
需要注意的是只有类自己(或他的子类)能够点用clone方法,其他类要求复制时是通过调用封装的createClone方法实现的。
/**
* 打印白色的字
* @author littlemotor
* @since 18.8.18
*/
public class WhitePrinter implements Printer {
private String content = "white";
public MessageBox(String content) {
this.content = content;
}
/**
* 包围显示
*/
@Override
public void print() {
System.out.println("白色字体:" + content);
}
@Override
public Printer clone() {
Printer p = null;
try {
p = (Printer)super.clone();
} catch(CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
}
2.6 BlackPrinter类
这个类的显示方式是在字符串下面加一行指定的字符串
public class BlackPrinter implements Printer {
private String content = "black";
public MessageUnderline(String content) {
this.content = content;
}
@Override
public void use() {
System.out.println("黑色字体:" + this.content);
}
@Override
public Print clone() {
Product p = null;
try {
p = (Printer)super.clone();
} catch(CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
}
2.7 Main类
/**
* 通过Manager类调用注册在Printer接口下方的不同类的实例 生成新的实例体会原型模式
*
* @author littlemotor
* @since 18.8.18
*/
public class Main {
public static void main(String[] args) {
//准备
Manager manager = new Manager();
Printer whitePrinter = new WhitePrinter("balabala");
Printer blackPrinter = new BlackPrinter("balabala");
manager.register("whitePrinter", whitePrinter);
manager.register("blackPrinter", blackPrinter);
//生成
Printer blackPrinter = manager.create("blackPrinter");
blackPrinter.print();
Product whitePrinter = manager.create("whitePrinter");
whitePrinter.print();
}
}
3. 小结
在类中尽量不要出现别的类名是为了实现组件复用,以达到只有.class文件时也可以复用的目的。
在Prototype原型模式中有三个角色,分别是
3.1 Prototype(原型)
Product角色负责定义用于复制现有实例来生成新实例的方法。
3.2 ConcretePrototype(具体的原型)
ConcretePrototype负责实现复制现有实例并生成新实例的方法。
3.3 Client(使用者)
由Manager类扮演此角色,Client角色使用复制实例的方法生成新的实例。
4. 拓展——Java中的clone方法和Clonable接口
4.1 调用clone方法的基本要求
被复制对象的类或父类必须实现java.lang.Clonable接口或其子接口,则可以调用clone方法,clone方法返回值是新复制出的实例(clone方法内部的处理是分配与要复制的实例相同大小的内存空间,接着将要复制的实例中的字段的值复制到所分配的内存空间中去)
4.2 Cloneable接口
Cloneable接口被称为标记接口(marker interface),其内部并没有声明任何方法,只是用来标记“可以使用clone方法进行复制”的。
4.3 Clone方法进行的是浅复制
clone方法进行的复制只是将被复制实例的字段值直接复制到新的实例中,并没有考虑字段中所保存实例的内容,例如,当字段保存的是数组时,使用clone方法进行复制,只会复制该数组的引用,并不会一一复制数组中的元素。更详细的深拷贝与浅拷贝的区别请参阅另一篇文章。