• 设计模式之Prototype模式


    通常我们会使用new 类名()的方法会去生成一个新的实例,但在开发过程中,有时候也会有“在不指定类名的前提下生成实例”的需求,那样,就只能根据现有实例来生成新的实例。

    有三种情况,不能根据类来生成实例:

    1. 对象种类繁多,无法将它们整合到一个类中时;
    2. 难以根据类生成实例的时;
    3. 想解耦框架与生成的实例时。

    不根据类来生成实例,而是根据实例来生成实例,就是Prototype模式,又叫原型模式。

    实例程序是将字符串放入方框中或者加上下划线显示:

    • Product接口
    package site.wangxin520.gof.prototype.framework;
    
    /**
     * 所有的需要new出来的对象全部需要实现Product接口
     * Product接口中,继承了Cloneable接口,方便子类调用clone()方法去复制本身对象
     * Product接口中,声明了use(String s)和createClone()抽象方法,具体实现通过子类进行
     * @author wangXgnaw
     *
     */
    public interface Product extends Cloneable{
        /**
         * 修饰字符串
         * @param s 被修饰的字符串
         */
        public void use(String s);
        /**
         * 复制(克隆)一个对象出来
         * @return Product 返回一个新对象,这个返回的对象并不是通过new出来的
         */
        public Product createClone();
    }
    • Manager类
    package site.wangxin520.gof.prototype.framework;
    
    import java.util.HashMap;
    
    import org.springframework.beans.factory.annotation.Autowired;
    
    /**
     * 使用Product接口来复制实例
     * 采用HashMap集合,来保存/注册对象
     * 这里是模仿了Spring源码中的注册和创建bean的方法
     * @author wangXgnaw
     *
     */
    @SuppressWarnings("all")
    public class Manager {
        
        /**
         * 注册对象用
         */
        private HashMap showcase=new HashMap();
        /**
         * 注册对象,模仿了Spring源码中的注册
         * @param name 对象名,在spring源码中可以使用alian别名和beanname名
         * @param product 实例化的对象,这里是注册一个原型对象,方便后面调用的时候克隆/复制出新对象
         */
        public void register(String name,Product product){
            showcase.put(name, product);
        }    
        /**
         * 重头戏
         * 根据传入的名字,获取到对象
         * 这里注意的是“返回对象”标注的那边,使用的是createclone()方法,来复制一个新实例。
         * @param protoname 需要实例化的对象名
         * @return Product 返回一个实现了Product接口的对象
         */
        public Product create(String protoname){
            Product product=(Product) showcase.get(protoname);
            //返回对象
            return product.createClone();
        }
        
    }
    • UnderlinePen类
    package site.wangxin520.gof.prototype;
    
    import site.wangxin520.gof.prototype.framework.Product;
    
    /**
     * 显示一个下划线,具体不做赘述,同MessageBox
     * @author wangXgnaw
     *
     */
    public class UnderlinePen implements Product{
    
        private char ulchar;
        public UnderlinePen(char ulchar){
            this.ulchar=ulchar;
        }
        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("");
        }
        
        public Product createClone(){
            Product product=null;
            try {
                product = (Product) clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return product;
        }
        
    }
    • MessageBox类
    package site.wangxin520.gof.prototype;
    
    import site.wangxin520.gof.prototype.framework.Product;
    
    /**
     * 显示消息框,实现了Product接口
     * @author wangXgnaw
     * 逻辑不做过多赘述
     */
    public class MessageBox implements Product{
    
        private char decochar;
        public MessageBox(char decochar){
            this.decochar=decochar;
        }
        public void use(String s){
            int lenght=s.getBytes().length;
            for (int i = 0; i < lenght+4; i++) {
                System.out.print(decochar);
            }
            System.out.println("");
            System.out.println(decochar+" "+s+" "+decochar);
            for (int i = 0; i < lenght+4; i++) {
                System.out.print(decochar);
            }
            System.out.println("");
        }
        
        /*
         * 创建一个克隆对象,由于继承了cloneable接口,所以采用的是clone()方法,直接克隆出自己本身出来
         * @see site.wangxin520.gof.prototype.framework.Product#createClone()
         */
        public Product createClone(){
            Product product=null;
            try {
                product = (Product) clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return product;
        }
    }
    • Prototype测试类
    package site.wangxin520.gof.prototype;
    
    import site.wangxin520.gof.prototype.framework.Manager;
    import site.wangxin520.gof.prototype.framework.Product;
    
    /**
     * ProtoType模式的测试类
     * @author wangXgnaw
     *
     */
    public class PrototypeTest {
        public static void main(String[] args) {
            
            //新建一个manager管理者,用于管理注册的bean,同Spring中一样
            Manager manager=new Manager();
            //先初始化一个类
            UnderlinePen ulpen=new UnderlinePen('~');
            MessageBox mbox1=new MessageBox('*');
            MessageBox mbox2=new MessageBox('/');
            //把初始化的类进行注册
            manager.register("strong message", ulpen);
            manager.register("warning box", mbox1);
            manager.register("slash box", mbox2);
            
            /**
             * 以上的方法,实现了spring框架中的注册容器的概念,可通过配置文件进行
             * 下面就是使用这个容器来为我们做事
             */
            
            //通过manager去创建一个新的product
            Product p1 = manager.create("strong message");
            p1.use("hello word");
            //为了方便观察,使用了一个地址值相同判断,看与之前初始化对象是否是一样的,后同
            System.out.println(p1==ulpen);
            
            Product p2 = manager.create("warning box");
            p2.use("hello word");
            System.out.println(p2==mbox1);
            Product p3 = manager.create("slash box");
            p3.use("hello word");
            System.out.println(p3==mbox2);
            
            
        }
    }
    • 控制台输出结果:

    image

  • 相关阅读:
    转:ITIL的開源軟件
    转:Asp.Net大型项目实践
    转:Ubuntu上apache多端口配置虚拟主机的方法
    转:JS 获取鼠标位置
    转:一切整合分享到新浪网易微博代码
    转:Facebook是如何发布代码的
    转:利用 Amazon Web Services 集成企业应用程序使用 Amazon SQS 发送 XML 消息
    sqlite3 常用操作
    转:4 款消息队列软件产品大比拼
    SQL Server 2008 列转行 实例
  • 原文地址:https://www.cnblogs.com/wangxinblog/p/7613503.html
Copyright © 2020-2023  润新知