• 《图解设计模式》读书笔记3-2 Prototype模式


    Prototype(原型)模式的由来

    创建一个实例,可以关键字new创建。但有时候,我们需要在不指定类名的前提下生成实例,比如:

    • 需要处理的对象种类繁多,无法整合到一个类里面,如果分别作为一个类,类的数量又太多了。

    • 很难通过代码生成实例:比如用户在画图工具中画出来的图形实例,如果用代码创建的话是非常困难的。我们可以先保存起来,需要时通过复制生成实例。

    • 想解耦框架和生成的实例时:不指定类名来生成实例,而是事先注册一个原型实例,通过复制该实例来生成新实例。比如打印机,不需要知道具体的文档内容,到需要的时候复印就行了,复印多少次都没问题。

    类图

    代码

    Product接口,继承Cloneable接口,实现Product接口的类都可以使用clone方法进行实例的复制。
    use方法表示怎么使用,具体怎么用,由子类来实现。
    createClone是用于复制实例的方法。

    public interface Product extends Cloneable {
        public abstract void use(String s);
        public abstract Product createClone();
    }
    

    Manager类,需要生成对象的类可以调用Manager类的create方法复制实例

    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();
        }
    }
    

    具体要进行对象复制的类

    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;
        }
    }
    
    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;
        }
    }
    

    如何使用

    public static void main(String[] args) {
            Manager manager = new Manager();
            UnderlinePen upen = new UnderlinePen('~');
            MessageBox mbox = new MessageBox('*');
            MessageBox sbox = new MessageBox('/');
    
            manager.register("Strong Message", upen);
            manager.register("Warning box", mbox);
            manager.register("Slash box", sbox);
    
    
            Product p1 = manager.create("Strong Message");
            p1.use("hello");
    
            Product p2 = manager.create("Warning box");
            p2.use("hello");
    
            Product p3 = manager.create("Slash box");
            p3.use("hello");
    }
    	//结果
    	"hello"
     	~~~~~
    	*********
    	* hello *
    	*********
    	/////////
    	/ hello /
    	/////////
    
    

    角色

    Prototype(原型)

    此角色负责定义用现有实例复制新实例的方法。对应于本例中的Product接口。

    ConcretePrototype(具体的原型)

    负责实现原型的方法。对应于本例中的MessageBox和UnderlinePen

    Client(使用者)

    负责使用原型的方法复制生成新的实例

    模式的类图

    我的理解

      说实话,由于经验所限,我不太能体会的到这个模式的好处。
      看看示例代码:代码实现的功能类似于一个文本编辑器,可以对文本进行下划线(UnderlinePen)和提示(MessageBox)两个操作。在一篇文章里面,可能有很多很多个下划线和提示操作。每一个都创建对象,创建过程简单还好,复杂的话那代码量就太恐怖了。所以搞一个原型对象,用到了就复制就行了。
      这只是我能理解的其中一个好处,更多内容可以看看这篇文章https://www.cnblogs.com/chenssy/p/3313339.html


    另外原型模式涉及到了对象的深拷贝和浅拷贝。区别就在于:复制对象时,是否复制对象中的引用指向的内存。那篇文章里面有解释。

  • 相关阅读:
    emacs 配置
    .Net微服务实践(五)[服务发现]:Consul介绍和环境搭建
    .Net微服务实践(四)[网关]:Ocelot限流熔断、缓存以及负载均衡
    .Net微服务实践(三)[网关]:Ocelot配置路由和请求聚合
    .Net微服务实践(二)[网关]:Ocelot介绍和快速开始
    .Net微服务实践(一)[框架]:微服务框架选型
    研发协同平台持续集成之Jenkins实践
    统一身份认证服务IdentityServer4实践
    DevOps平台架构演进
    ABP框架
  • 原文地址:https://www.cnblogs.com/qianbixin/p/10992895.html
Copyright © 2020-2023  润新知