zoukankan      html  css  js  c++  java
  • 设计模式之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

  • 相关阅读:
    Nginx internal 指令限制访问图片资源文件
    Laravel 5 中文文档 CHM 版
    Educational Codeforces Round 89 (Rated for Div. 2)
    Markdown写的第一篇文章,猜猜里边有什么东西吧!
    Git暂存流程
    Java BIO、NIO与AIO的介绍(学习过程)
    如何在Mac中安装telnet
    使用IDEA编译java程序时,出现的编译错误: error:java:错误:不支持发行版本5
    Java中请优先使用try-with-resources而非try-finally
    Redis入门学习(学习过程记录)
  • 原文地址:https://www.cnblogs.com/wangxinblog/p/7613503.html
Copyright © 2011-2022 走看看