场景

场景1:
(1) 如果一个对象,我们希望拷贝一个这个对象
(2) 就是弄出来这个类的另外一个实例,实例的属性跟之前的实例是一模一样的
场景2:
(1)电商项目中各种对象VO,DTO,DO数据转换就可以使用原型模式,将一个基础数据拷贝到另一个数据对象里面去。
(2)刚从DAO中查询出来的一个ProductDO,包含了10个字段,然后接着在service中处理完成之后,需要返回一个ProductDTO,包含20个字段,此时别使用new ProductDTO,set,set...;应该使用原型模式,将ProductDO里面的数据直接拷贝到ProductDTO中去。
场景3:
(1)仓储中心创建的采购入库单和采购单大部分字段是一样的,创建采购入库单的时候,获取到的是一个采购单,此时你可能需要将采购单数据拷贝一份到采购入库单中去。

内容

1. 不使用设计模式

1.1 类图

image.png

1.2 代码

public class NonPattern2 {
    /**
     * 定义一个对象:里面有其他对象的引用,我们实现拷贝
     */
    public static void main(String[] args) {
        //1. 创建一个对象,进行拷贝
        Product product = new Product("汽车", new Component("汽车轮胎"));
        
        //2.手动来拷贝
        Product copyedProduct = new Product(product.getName(),product.getComponent());
        System.out.println("product:"+product);
        System.out.println("copyedProduct:"+copyedProduct);

        /**
         * 输出:
         * product:Product{name='汽车', component=Component{name='汽车轮胎'}}
         * copyedProduct:Product{name='汽车', component=Component{name='汽车轮胎'}}
         */
    }

    //===================产品实体类====================
    public static class Product{
        private String name;
        private Component component;
        public Product(String name,Component component){
             this.component =component;
             this.name = name;
        }

        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Component getComponent() {
            return component;
        }
        public void setComponent(Component component) {
            this.component = component;
        }

        @Override
        public String toString() {
            return "Product{" +
                    "name='" + name + '\'' +
                    ", component=" + component +
                    '}';
        }
    }

    public static class Component{
        private String name;
        public Component(String name){
               this.name = name;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "Component{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
}

2. 使用设计模式

  1. 这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。
  2. 这里实现原型拷贝最主要的是对象里面的clone方法。

2.1 类图

image.png

2.2 代码

public class PrototypePattern2 {
    public static void main(String[] args) {
        try {
            Product product = new Product("汽车", new Component("汽车轮胎"));
            Product copyedProduct = (Product) product.clone();
            System.out.println("product:"+product);
            System.out.println("copyedProduct:"+copyedProduct);
            /**
             * 输出:
             * product:Product{name='汽车', component=Component{name='汽车轮胎'}}
             * copyedProduct:Product{name='汽车', component=Component{name='汽车轮胎'}}
             */
        }catch (Exception e){
            e.printStackTrace();
        }
    }
//=====================产品类======================
     public static class Product{
       private String name;
       private Component component;
       public Product(String name,Component component){
           this.name = name;
           this.component = component;
       }

       @Override
       protected Object clone() throws CloneNotSupportedException {
        //浅拷贝,就是我们现在的一个实现 就是仅仅简单的对当前所有的变量进行一个拷贝
        // return new Product(getName(),getComponent());

        // 深考别,递归对自己引用的对象也进行拷贝
        return new Product(getName(),(Component) getComponent().clone());
       }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Component getComponent() {
            return component;
        }

        public void setComponent(Component component) {
            this.component = component;
        }

        @Override
        public String toString() {
            return "Product{" +
                    "name='" + name + '\'' +
                    ", component=" + component +
                    '}';
        }
}

    public static class Component{
      private String name;
      public Component(String name){
          this.name = name;
      }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return new Component(getName());
    }

     public String getName() {
        return name;
     }
     public void setName(String name) {
        this.name = name;
     }

    @Override
    public String toString() {
        return "Component{" +
                "name='" + name + '\'' +
                '}';
       }
   }
}

3.总结

3.1 不使用设计模式对比

  1. 代码的拷贝逻辑,是每个要拷贝的调用方(main方法)自己来实现的;相同的拷贝逻辑会分散在很多不同的地方,如果拷贝逻辑改变了,多个调用的地方都要修改代码。
  2. 可维护性、可扩展性,很差。

3.2 使用原型模式

  1. 原对象拷贝直接使用原对象的clone方法,是在目标对象自身,而不是调用方,调用方不用关注拷贝逻辑。
  2. 扩展性强:如果目标对象添加了新属性,拷贝逻辑可直接在目标对象的clone()修改。

startshineye
91 声望26 粉丝

我在规定的时间内,做到了我计划的事情;我自己也变得自信了,对于外界的人跟困难也更加从容了,我已经很强大了。可是如果我在规定时间内,我只有3分钟热度,哎,我不行,我就放弃了,那么这个就是我自己的问题,因为你自己...