• GOF设计模式——Prototype模式


    一、什么是Prototype模式?

            在编程中,我们可以使用new关键字指定类名来生成类的实例,但是有时候也会有不指定类名的前提下生成实例。因为有时候对象种类繁多,无法将它们整合到一个类中;或者,生成实例的过程过于复杂,难以根据类生成实例;又或者,想要将类与框架解耦。这时,为了能够在不使用类名的情况下生成实例,可以使用Prototype模式,Prototype模式又叫原型模式,专门做一些“复制”的操作。

    二、Prototype模式思想

    Client负责调用Prototype接口生成实例,具体的实例生成的过程交给ConcretePrototype实现类,那么在Client调用Prototype这整个过程中都没有涉及ConcretePrototype类名。

    三、具体实例

            假设现在要做一个功能,将字符串放入方框中显示,或者加上下划线等操作。

    1、Manager类

    package com.cjs.Prototype;
     
    import java.util.HashMap;
     
    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 product = (Product) showCase.get(protoName);
            return product.createClone();
        }
    }

    Manager类定义了两个方法,一个用于注册类,另一个是根据关键信息创建实例。

    2、Product类

    package com.cjs.Prototype;
     
    public abstract class Product implements Cloneable {
        public abstract void use(String s);
     
        public final Product createClone() {
            Product product = null;
     
            try {
                product = (Product) clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
     
            return product;
        }
    }

    Product类定义了一个抽象方法use,用于让子类实现时拥有个性的行为;还有一个被final修饰的createClone方法,用于复制类,生成实例,这里用到了Template Method模式。

    3、UnderlinePen类

    package com.cjs.Prototype;
     
    public class UnderlinePen extends 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("");
        }
    }

    4、MessageBox类

    package com.cjs.Prototype;
     
    public class MessageBox extends 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();
        }
    }

    5、Main类

    package com.cjs.Prototype;
     
    public class Main {
        public static void main(String[] args) {
            Manager manager = new Manager();
            UnderlinePen underlinePen = new UnderlinePen('~');
            System.out.println("main underlinePen's hashCode = " + underlinePen.hashCode());
            MessageBox messageBox1 = new MessageBox('*');
            System.out.println("main messageBox1's hashCode = " + messageBox1.hashCode());
            MessageBox messageBox2 = new MessageBox('/');
            System.out.println("main messageBox2's hashCode = " + messageBox1.hashCode());
            manager.register("strong message", underlinePen);
            manager.register("warning box", messageBox1);
            manager.register("slash box", messageBox2);
     
            Product p1 = manager.create("strong message");
            System.out.println("Prototype p1's hashCode = " + p1.hashCode());
            Product p2 = manager.create("warning box");
            System.out.println("Prototype p2's hasCode = " + p2.hashCode());
            Product p3 = manager.create("slash box");
            System.out.println("Prototype p3's hasCode = " + p2.hashCode());
     
            p1.use("hello world");
            p2.use("hello world");
            p3.use("hello world");
        }
    }

    输出结果:


    Main类里面对于每个生成的实例都打印出它们的hashCode,从Console窗口可以看出,即使是复制出来的实例,它们都不是同一个对象。在整个创建实例的过程中,除了一开始注册的时候用到了类名,其余的只用到了关键字,如“strong message”,“warning box”等,就可以创建对应的实例对象。

    四、Prototype的作用

    1、对象种类繁多,实现功能类似,使用Prototype模式可以便于源程序的管理,合理减少了类的数量;

    2、在难以根据类生成实例的时候,有时候需要创建的类非常复杂,如果经常需要用到此类的对象,那么每次创建的时候会非常繁琐,相反,通过实例生成实例的方式会简单得多。

    3、解耦

            前面也提过很多次,一旦在某个类文件使用了一个类名来创建实例对象,那么这个类文件就跟使用的这个类具有高度的耦合性,特别是如果框架也这么做,那么这个框架就只适用某些类。

  • 相关阅读:
    centos7 安装 tesseract4.1
    08 图的数据结构和算法
    07 树形结构及其算法
    05 数组与链表算法
    06 堆栈与队列算法
    04 查找与哈希算法
    03 排序算法
    javascript 标签轮播
    tomcat URI get 参数中文传到后台 乱码 URIEncoding
    javascript 标签切换
  • 原文地址:https://www.cnblogs.com/SysoCjs/p/10327182.html
Copyright © 2020-2023  润新知