原型模式

原型模式

  • 作用:用原型实例指定创建对象的种类,并且通过复制(克隆)这些原型创建新的对象。

  • 使用频率:不常用,使用场景非常少。

  • 特点:通过克隆的方式创建对象。

  • 境界:写代码的最高境界就是crtl+c/v,建立自己的技术平台,复用代码,修改代码。

  • 关键点:

    • 抽象原型类:它是声明克隆方法的接口,是所有具体原型类的公共父类,可以是抽象类也可以是接口,甚至可以是具体实现类。
    • 具体原型类:它实现抽象原型类中声明的方法,在克隆方法中返回自己的一个克隆对象。
    • 客户类:具体原型对象克隆自身从而创建一个全新的对象。
  • 使用场景:构造函数复杂,这样通过new来创建对象需要非常繁琐的数据准备。

  • 举例

    • 简历:将一份简历,复制多次,得到多份简历。
      在这里插入图片描述

    • 代码示例:

      • Resume:

        package com.prototype;
        public interface Resume {
            public Resume clone();
        }
        
      • ConcreteResume

        package com.prototype;
        public class ConcreteResume implements Resume {
            @Override
            public Resume clone() {
                Resume re = new ConcreteResume();
                return re;
            }
        }
        
      • Client

        package com.prototype;
        public class Client {
            public static void main(String[] args) {
                Resume re   = new ConcreteResume();
                re.clone();
                re.clone();
                re.clone();
                re.clone();
            }
        }
        
      • 上面实际上,把new 用代码隐藏了,本质上对象的产生还是靠new产生的,只是耐看了一些上面具备了原型模式的形态,但产生的对象并不能复制对象的当前运行时状态,所以需要做一些改进。

      • 使用克隆

        • 克隆的得到的是一个新的对象,但是这个新对象的内容是克隆对象的当前运行时内容

        • 只有实现了Cloneable这个接口的类才可以被拷贝

        • 在克隆对象的过程中,没有调用构造函数。因为Object类的clone方法原理是从堆内存以二进制流的方式进行拷贝,重新分配一个内存块,将当前内存状态拷贝到新开辟的的内存,并将堆中开辟的新内存地址返回给栈中的对象引用。

        • 克隆分为深克隆和浅克隆,只要区别在于是否支持对象引用类型的成员变量的复制。结合下面简历例子,调用对象clone方法这里是浅拷贝。

          public class Test {
              public static void main(String[] args) throws CloneNotSupportedException {
                  Resume re = new Resume();
                  re.setAge(10);
                  re.setName("x1同学");
                  re.setHobby(new String[]{"吃饭","睡觉","打豆豆"});
                  System.out.println(re);
                  re.setAge(11);
                  Resume re1 = (Resume) re.clone();
                  String [] hobbies = re1.getHobby();
                  hobbies[0]="打游戏";
                  re1.setHobby(hobbies);
                  System.out.println(re1);
                  System.out.println(re);
          
              }
          }
          

          在这里插入图片描述

        • 运行结果

          Resume{name='x1同学', age=10, hobby=[吃饭, 睡觉, 打豆豆]}
          Resume{name='x1同学', age=11, hobby=[打游戏, 睡觉, 打豆豆]}
          Resume{name='x1同学', age=11, hobby=[打游戏, 睡觉, 打豆豆]}
          
        • 举例

          • Reume

            package com.prototype;
            import java.util.Arrays;
            public class Resume implements Cloneable{
               // public Resume clone();
                private String name;
                private Integer age;
                private  String[] hobby;
                public String getName() {
                    return name;
                }
            
                public void setName(String name) {
                    this.name = name;
                }
            
                public Integer getAge() {
                    return age;
                }
            
                public void setAge(Integer age) {
                    this.age = age;
                }
            
                public String[] getHobby() {
                    return hobby;
                }
            
                public void setHobby(String[] hobby) {
                    this.hobby = hobby;
                }
            
                @Override
                protected Object clone() throws CloneNotSupportedException {
                    return super.clone();
                }
            
                @Override
                public String toString() {
                    return "Resume{" +
                            "name='" + name + '\'' +
                            ", age=" + age +
                            ", hobby=" + Arrays.toString(hobby) +
                            '}';
                }
            }
            
          • Test

            package com.prototype;
            public class Test {
                public static void main(String[] args) throws CloneNotSupportedException {
                    Resume re = new Resume();
                    re.setAge(10);
                    System.out.println(re);
                    re.setAge(11);
                    Resume re1 = (Resume) re.clone();
                    System.out.println(re1);
                }
            }
            
          • 结果

            Resume{name='null', age=10, hobby=null}
            Resume{name='null', age=11, hobby=null}
            
          • 由上面结果可知,克隆产生新的对象,新对象的内容是克隆对象的当前运行时状态。

          • ==用在基本数据类型,比较的是值,用来引用独享,比较的是对象的地址。

        • 深拷贝:深拷贝在对象拷贝(克隆)时,连同引用类型也拷贝一份。修改Reume中clone方法即可。

              @Override
              protected Object clone() throws CloneNotSupportedException {
                  Resume re = (Resume) super.clone();
                  String [] hobbies = re.getHobby().clone();
                  re.setHobby(hobbies);
                  return re;
              }
          
        • 运行结果

          Resume{name='x1同学', age=10, hobby=[吃饭, 睡觉, 打豆豆]}
          Resume{name='x1同学', age=11, hobby=[打游戏, 睡觉, 打豆豆]}
          Resume{name='x1同学', age=11, hobby=[吃饭, 睡觉, 打豆豆]}
          
        • clone比new效率高,只有构造函数特别复杂是,clone优势才会显示出来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值