zoukankan      html  css  js  c++  java
  • 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、解耦

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

  • 相关阅读:
    UVALive 5983 MAGRID DP
    2015暑假训练(UVALive 5983
    poj 1426 Find The Multiple (BFS)
    poj 3126 Prime Path (BFS)
    poj 2251 Dungeon Master 3维bfs(水水)
    poj 3278 catch that cow BFS(基础水)
    poj3083 Children of the Candy Corn BFS&&DFS
    BZOJ1878: [SDOI2009]HH的项链 (离线查询+树状数组)
    洛谷P3178 [HAOI2015]树上操作(dfs序+线段树)
    洛谷P3065 [USACO12DEC]第一!First!(Trie树+拓扑排序)
  • 原文地址:https://www.cnblogs.com/SysoCjs/p/10327182.html
Copyright © 2011-2022 走看看