[设计模式扫盲]---(2)原型模式

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方法,然后在该方法内部进行初始化处理。

 

 

参考资料 :《图解设计模式》

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值