设计模式 _第七招式_原型模式

版权声明:做一个有尊严的生产者 https://blog.csdn.net/qq_36918149/article/details/82938430

一、定义

用原型实例指定创建对象种类,并且通过拷贝这些原型创建新的对象。原型模式的核心是clone方法,通过该方法进行对象的拷贝,Java提供了一个Cloneable接口来标示这对象是可以拷贝的,为什么说是“标示”呢 ?JDK源码中Cloneable 接口是一个方法都没有,这个接口只是一个标记的作用,在jvm中具有这个标识才可能被拷贝,且类中必须要重新clone()方法,覆写了Object类中的clone方法。

二、代码演示

通过一个部门给不同的人员发相同内容的邮件为例,邮件里面不同的是收件人地址,其它都是一样的,通过clone产生公用属性一直,特性不一致的的mail。
2.1 邮件类

public class Mail implements Cloneable {
    //收件人
    private String receiver ;
    //邮件名称
    private String subject ;
    //称谓
    private String appellation ;
    //邮件内容
    private String context;
    //邮件签名
    private String tail ;
    public String getReceiver() {
        return receiver;
    }
    public void setReceiver(String receiver) {
        this.receiver = receiver;
    }
    public String getSubject() {
        return subject;
    }
    public void setSubject(String subject) {
        this.subject = subject;
    }
    public String getAppellation() {
        return appellation;
    }
    public void setAppellation(String appellation) {
        this.appellation = appellation;
    }
    public String getContext() {
        return context;
    }
    public void setContext(String context) {
        this.context = context;
    }
    public String getTail() {
        return tail;
    }
    public void setTail(String tail) {
        this.tail = tail;
    }
    @Override
    public  Mail clone(){
        Mail  mail = null ;
        try{
            mail = (Mail)super.clone();
        }catch (Exception e){
              e.printStackTrace();
        }
        return  mail ;
    }
  @Override
    public String toString(){
      String result = "Mail{";
      result = result + "receiver:"+receiver + "|";
      result = result + "appellation:"+appellation + "|";
      result = result + "context:"+context + "|";
      result = result + "}";
      return  result;
  }
}

2.2 应用场景类

public class Client {
 public  static void  main(String args[]){
     Mail  mails = new Mail();
     mails.setContext("xx部门通告邮件");
     mails.setAppellation("admin");
     //下面发送给不同的收件人
     Mail  mailNew1 = mails.clone();
     mailNew1.setReceiver("[email protected]");
     System.out.println(mailNew1.toString());
     System.out.println("---------------------------------");
     Mail  mailNew2 = mails.clone();
     mailNew2.setReceiver("[email protected]");
     System.out.println(mailNew2.toString());
 }
}

结果:

Mail{receiver:[email protected]|appellation:admin|context:xx部门通告邮件|}
---------------------------------
Mail{receiver:[email protected]|appellation:admin|context:xx部门通告邮件|}

三、优点

3.1 性能优良
原型模式是在内存中通过二进制流的拷贝,要比直接new一个对象性能要好,特别是要在一个循环体内产生大量的对象是,原型模式可以更好的体现其优点。
3.2 逃避构造函数约束
这既是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的。有点事减少了约束,缺点是需要大家在实际应用中考虑。

四、缺点

4.1 可能有线程安全问题
在多线程环境下,多个线程公用一个对象本身是有线程安全隐患的, 这在实际项目中,需要着重考虑。

五、应用场景

5.1 优化资源场景
类初始化需要消化非常多的资源,这个资源包括数、硬件。
5.2 性能和安全要求的场景
通过new一个对象需要频繁的准备数据或访问权限,则可以通过使用原型模式。
5.3 一个对象多个修改者场景
一个对象需要提供给其它的对象访问,而且各个调用者可能都需要修改其值,可以用原型模式。
在实际项目中,原型模式单独使用的很少,一般是和工厂模式一起出现,通过clone的方法创建一个对象,然后由工程方法提供给调用者。

六、注意事项

6.1 原型模式必备两要素
A、实现Cloneable接口;B、重写Object类clone方法;
6.2 构造函数不会被执行
6.3 注意浅拷贝和深拷贝的区别
使用原型模式的时候,有一些类中的成员变量可能不会被拷贝。应用的成员变量必须满足两个条件才不会被拷贝。一是 类的成员变量,而不是方法内变量;二是必须是一个可变的引用对象,而不是一个不可变对象或原始类型。

猜你喜欢

转载自blog.csdn.net/qq_36918149/article/details/82938430