设计模式之原型模式:以自己为原型,自己实现自己的对象拷贝逻辑

场景

场景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 类图
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 类图
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()修改。
相关推荐
好家伙VCC16 分钟前
区块链双向支付通道实战:从签名到结算
java·后端·区块链·asp.net
ss27325 分钟前
【入门OJ题解】分苹果问题(Python/Java/C 实现)
java·c语言·python
weikecms37 分钟前
美团霸王餐报名API接口
java·开发语言
李白的天不白42 分钟前
配置mysql密码
java
何中应43 分钟前
Nexus如何上传JAR包
java·maven·jar
我登哥MVP1 小时前
Spring Boot 从“会用”到“精通”:参数解析原理
java·spring boot·后端·spring·servlet·maven·intellij-idea
Wenzar_1 小时前
VITS+Whisper微调:低延迟TTS实战
java·人工智能·whisper
创可贴治愈心灵1 小时前
AI浪潮下C#就业前景剖析:深耕C#为主,按需选修Java与Python
java·人工智能·c#
huohaiyu1 小时前
深入解析Java垃圾回收机制
java·开发语言·算法·gc
SunnyDays10112 小时前
如何在 Java 中实现 OFD 与 PDF 格式互转
java·开发语言