Author:赵志乾
Date:2019-03-09
Declaration:All Right Reserved!!!
1、模型解释
所谓的原型模式,是指在进程运行期间,通过对进程内存空间中已有实例的拷贝来生成新实例的设计理念。
我们知道,开发中生成实例最常用的方式是调用类的构造函数。但在某些场景下,我们并不希望通过类的构造函数调用来实例化,比如:有大量近似实例无法整合到一个类中,如果通过构造函数来实例化,便需要大量类文件与之对应,不便于代码的维护。而原型模式则可以在进程初始阶段按需生成大量实例,在需要新生成实例时,可以通过对现有实例拷贝来生成新实例。
2、模型补充
原型模式核心点是生成实例的途径,其不在是传统的、通过构造函数调用的方式,而是在初始阶段通过构造函数调用,在进程内存空间中构建实例,之后在需要新生成实例时,便以内存空间中的现有实例为基础,通过复制的方式完成实例生成。其除了可以解决上述中的大量实例对象无法整合的问题外,还可以用于解决以下两种问题:
在某些场景下,随时间的推移,实例越来越复杂。此时要构建一个相同的实例,通过构造函数的调用将会非常的复杂,而原型模式则依据现有实例通过复制的方式便可将问题简单化。
在某些框架中,为了解耦框架和实例,也可以用通过原型模式的理念来解决。在初始阶段,通过注册的方式先注册实例,然后在需要的时候,以注册的实例为基础,通过复制的方式进行实例化。
3、实现
原型接口:
package com.zhaozhiqian;
// 1、组件接口,定义功能方法和实例拷贝方法;
// 注:扩展Cloneable接口是为了能够调用clone方法完成实例拷贝(java)
public interface IModule extends Cloneable{
// 2、对外提供功能定义
void use(String s);
// 3、实例拷贝方法,依据实例生成新实例
IModule createByClone();
}
原型实现:
package com.zhaozhiqian.impl;
import com.zhaozhiqian.IModule;
public class Hello implements IModule {
private String prefix="";
public Hello(String prefix){
this.prefix = prefix+":";
}
@Override
public void use(String s) {
System.out.println(this.prefix+s+" hello!");
}
@Override
public IModule createByClone() {
IModule result = null;
try {
// 通过实例拷贝生成新实例
result = (IModule) clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return result;
}
}
原型管理容器:
package com.zhaozhiqian.impl;
import com.zhaozhiqian.IModule;
import java.util.HashMap;
public class ModuleManager {
// 存放名称和实例映射关系的容器
private HashMap<String, IModule> registryCenter = new HashMap<>();
// 注册名称和实例映射的方法
public void register(String name, IModule module) {
this.registryCenter.put(name, module);
}
// 依据名称,从内存中的实例拷贝出新实例
public IModule create(String moduleName){
IModule module = this.registryCenter.get(moduleName);
if(module==null){
return null;
}
return module.createByClone();
}
}
测试代码:
package com.zhaozhiqian;
import com.zhaozhiqian.impl.Hello;
import com.zhaozhiqian.impl.ModuleManager;
public class Main {
public static void main(String[] args) {
// 初始阶段:完成内存实例的生成
ModuleManager manager = new ModuleManager();
manager.register("morning", new Hello("morning"));
manager.register("afternoon", new Hello("afternoon"));
// 原型模式工作阶段:通过拷贝生成新实例
IModule moringHello = manager.create("morning");
moringHello.use("小王");
IModule afternoonHello = manager.create("afternoon");
afternoonHello.use("小王");
}
}
输出结果:
morning:小王 hello!
afternoon:小王 hello!
4、java中的特例
java语言中为我们提供了用于实例拷贝的clone方法,其定义于java.lang.Object中。由于Object类是所有java类的父类,所以所有的java类都继承了clone方法。
虽然java中的所有类都继承了clone方法,但clone方法的调用需要一个前提:实现Cloneable接口。这个接口中没有声明任何方法,其只是用来标记“可以使用clone方法进行复制”,这样的接口也被称为标记接口。
需要注意的一点是java中的clone方法所进行的是浅复制,即只将被复制实例的字段值直接复制到新的实例中。如果要进行深复制,需要从新clone方法。在重新clone方法时,不要忘记使用super.clone()来调用父类clone方法。
clone方法只是完成实例的复制,从而生成新的实例。这一过程中,并不会调用构造函数,如果需要在生成实例时进行特殊的初始化处理,需要重写clone方法,然后在该方法内部进行初始化处理。
参考资料 :《图解设计模式》