十九、原型模式—通过复制生产实例 #和设计模式一起旅行#

拔一根猴毛,变出十万个孙悟空

故事背景

在java中,我们一般创建实例的时候可以使用了new 关键词指定类名来生成类的实例。例如:

Preson p = new Person();
或者
Person p = Person.getInstance();

但是是在实际开发过程中,有时候会有“不指定类名的前提下生成实例”的需求。这种情况下,就不能通过上面的这种方式生成实例!

除了上面这种情况外,还有就是 对象的种类繁多,如果每一个都作为一个类,那么要编写很多类文件!

可以通过一个原型对象克隆出多个一模一样的对象!

原型模式和单例模式区别:
单例模式:在系统只存在或者说只创建唯一的一个对象。
原型模式:在系统中存在或者说创建多个对象。

故事主角

原型模式(Prototype Pattern):使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

原型模式类图

  • Prototype(抽象原型类):它是声明克隆方法的接口,是所有具体原型类的公共父类,可以是抽象类也可以是接口,甚至还可以是具体实现类。

  • ConcretePrototype(具体原型类):它实现在抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象。

  • Client(客户类):让一个原型对象克隆自身从而创建一个新的对象,在客户类中只需要直接实例化或通过工厂方法等方式创建一个原型对象,再通过调用该对象的克隆方法即可得到多个相同的对象。由于客户类针对抽象原型类Prototype编程,因此用户可以根据需要选择具体原型类,系统具有较好的可扩展性,增加或更换具体原型类都很方便。

原型模式的核心在于如何实现克隆方法,下种在Java语言中常用的克隆实现方法:

  • Java语言提供的clone()方法(浅拷贝)
  • Java语言提供的序列化方法(深拷贝)

武功修炼

使用原型管理器 演示简单的原型模式:

// 抽象原型类
public interface Product extends Cloneable{
    /**
     * 产品使用方法
     * @param str
     */
    abstract void use(String str);

    /**
     *  复制实例对象的方法
     * @return
     */
    abstract Product createClone();
}
public class MessageProduct implements Product{

    private String flagStr;

    public  MessageProduct(){}

    public  MessageProduct(String str){
        this.flagStr = str;
    }

    @Override
    public void use(String str) {
        for (int i = 0; i < str.length(); i++) {
            System.out.print(flagStr);

        }

        System.out.println("");
        System.out.println("-----"+ str+"---------");

        for (int i = 0; i < str.length(); i++) {
            System.out.print(flagStr);

        }
    }

    @Override
    public Product createClone() {
        Product product = null;

        try {
            product = (Product) clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return product;
    }
}
public class UnderLineProduct implements Product {

    private String flagStr;

    public  UnderLineProduct(){}

    public  UnderLineProduct(String str){
        this.flagStr = str;
    }

    @Override
    public void use(String str) {

        for (int i = 0; i < str.length(); i++) {
            System.out.print(flagStr);

        }

        System.out.println("");

        System.out.println(str);

        for (int i = 0; i < str.length(); i++) {
            System.out.print(flagStr);

        }
        System.out.println("");
    }

    @Override
    public Product createClone() {
        Product product = null;

        try {
            product = (Product) clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return product;
    }

}
// Product 的管理器
public class ManageProduct {

    private HashMap map = new HashMap();

    /**
     * 通过名称注册Product
     * @param name
     * @param product
     */
    public void register(String name,Product product){
        map.put(name, product);
    }

    /**
     * 创建Product
     * @param protoName
     * @return
     */
    public Product createProduct(String protoName){
        Product product = (Product)map.get(protoName);

        return product.createClone();
    }

public class TestMain {

    public static void main(String[] args) {

        ManageProduct manageProduct = new ManageProduct();

        // 准备
        manageProduct.register("mesOne",new UnderLineProduct("|"));
        manageProduct.register("mesTwo",new UnderLineProduct("——"));
        manageProduct.register("mesThree",new MessageProduct("(*)"));

        //生成

        Product p1 = manageProduct.createProduct("mesOne");
        p1.use("你好,China!");
        Product p2 = manageProduct.createProduct("mesTwo");
        p2.use("你好,China!");
        Product p3 = manageProduct.createProduct("mesThree");
        p3.use("你好,China!");


    }
}


|||||||||
你好,China!
|||||||||
——————————————————
你好,China!
——————————————————
(*)(*)(*)(*)(*)(*)(*)(*)(*)
-----你好,China!---------
(*)(*)(*)(*)(*)(*)(*)(*)(*)

总结

优点:

  • 原型模式可以简化对象的创建过程,通过复制一个已有实例可以提高新实例的创建效率。
  • 在客户端可以针对抽象原型类进行编程,而将具体原型类写在配置文件中,增加或减少产品类对原有系统都没有任何影响。

缺点:

  • 需要为每一个类配备一个克隆方法,而且该克隆方法位于一个类的内部,当对已有的类进行改造时,需要修改源代码,违背了“开闭原则”。

  • 在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重的嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来可能会比较麻烦。

参考

本专栏文章列表

一、设计模式-开篇—为什么我要去旅行? #和设计模式一起旅行#
二、设计模式-必要的基础知识—旅行前的准备 #和设计模式一起旅行#
三、设计模式介绍—她是谁,我们要去哪里? #和设计模式一起旅行#
四、单例模式—不要冒充我,我只有一个! #和设计模式一起旅行#
五、工厂模式—旅行的钱怎么来 #和设计模式一起旅行#
六、策略模式—旅行的交通工具 #和设计模式一起旅行#
七、观察者模式——关注我,分享旅途最浪漫的瞬间! #和设计模式一起旅行#
八、装饰者模式—巴厘岛,奶茶店的困扰! #和设计模式一起旅行#
九、命令模式—使用命令控制奶茶店中酷炫的灯 #和设计模式一起旅行#
十、模板方法模式—制作更多好喝的饮品! #和设计模式一起旅行#
十一、代理模式 —专注,做最好的自己!#和设计模式一起旅行#
十二、适配器模式——解决充电的烦恼 #和设计模式一起旅行#
十三、外观模式—— 简化接口 #和设计模式一起旅行#
十四、迭代器模式—— 一个一个的遍历 #和设计模式一起旅行#
十五、组合模式—— 容器与内容的一致性 #和设计模式一起旅行#
十六、状态模式—用类表示状态 #和设计模式一起旅行#
十七、访问者模式-访问数据结构并处理数据 #和设计模式一起旅行#
十八、职责链模式-推卸责任,不关我的事,我不管!#和设计模式一起旅行#
十九、原型模式—通过复制生产实例 #和设计模式一起旅行#
二十、设计模式总结—后会有期 #和设计模式一起旅行#


如果您觉得这篇博文对你有帮助,请点赞或者喜欢,让更多的人看到,谢谢!

如果帅气(美丽)、睿智(聪颖),和我一样简单善良的你看到本篇博文中存在问题,请指出,我虚心接受你让我成长的批评,谢谢阅读!
祝你今天开心愉快!


欢迎访问我的csdn博客,我们一同成长!

不管做什么,只要坚持下去就会看到不一样!在路上,不卑不亢!

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 成长之路 设计师:Amelia_0503 返回首页