一:原型模式的定义
        --->用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
        --->原型模式(Prototype Pattern)的简单程度仅次于单例模式和迭代器模式。正是由于简单,使用的场景才非常地多
        --->原型模式的核心是一个clone方法,通过该方法进行对象的拷贝,Java提供了一个Cloneable接口来标示这个对象是可拷贝的,为什么说是“标示”呢?翻开JDK的帮助看看Cloneable是一个方法都没有的,这个接口只是一个标记作用,在JVM中具有这个标记的对象才有可能被拷贝。那怎么才能从“有可能被拷贝”转换为“可以被拷贝”呢?方法是覆盖clone()方法,是的,你没有看错是重写clone()方法,看看我们上面Mail类中的clone方法.该方法重写了Object对象的方法

二:原型模式的优点

        ● 性能优良
               ---> 原型模式是在内存二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其优点。

        ● 逃避构造函数的约束
               --->这既是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的(参见13.4节)。优点就是减少了约束,缺点也是减少了约束,需要大家在实际应用时考虑。


三:原型模式的应用场景

        ● 资源优化场景
                --->类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
        ● 性能和安全要求的场景
                --->通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
        ● 一个对象多个修改者的场景
                --->一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
                --->在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过clone的方法创建一个对象,然后由工厂方法提供给调用者。原型模式已经与Java融为一体,大家可以随手拿来使用。


四:原型模式的注意事项
        ---> 构造函数不会被执行
        --->注意浅拷贝。你可能会比较奇怪,为什么在Mail那个类中就可以使用String类型,而不会产生由浅拷贝带来的问题呢?内部的数组和引用对象才不拷贝,其他的原始类型比如int、long、char等都会被拷贝,但是对于String类型,Java就希望你把它认为是基本类型,它是没有clone方法的,处理机制也比较特殊,通过字符串池(stringpool)在需要的时候才在内存中创建新的字符串,读者在使用的时候就把String当做基本类使用即可。
        --->使用原型模式时,引用的成员变量必须满足两个条件才不会被拷贝:一是类的成员变量,而不是方法内变量;二是必须是一个可变的引用对象,而不是一个原始类型或不可变对象。
        --->深拷贝还有一种实现方式就是通过自己写二进制流来操作对象,然后实现对象的深拷贝,这个大家有时间自己实现一下
        --->深拷贝和浅拷贝建议不要混合使用,特别是在涉及类的继承时,父类有多个引用的情况就非常复杂,建议的方案是深拷贝和浅拷贝分开实现。

五:clone和fianl两个冤家
        --->你要实现深拷贝的梦想在final关键字的威胁下破灭了,路总是有的,我们来想想怎么修改这个方法:删除掉final关键字,这是最便捷、安全、快速的方式
        --->你要使用clone方法,在类的成员变量上就不要增加final关键字。

六:原型模式最佳实践

        --->可以这样理解:一个对象的产生可以不由零起步,直接从一个已经具备一定雏形的对象克隆,然后再修改为生产需要的对象。也就是说,产生一个人,可以不从1岁长到2岁,再到3岁......也可以直接找一个人,从其身上获得DNA,然后克隆一个,直接修改一下就是30岁了!我们讲的原型模式也就是这样的功能



七:原型模式例子

【1】原型模式的模板

 1 package com.yeepay.sxf.template8;
 2 /**
 3  * 邮件
 4  * @author sxf
 5  * 
 6  * 原型模式:(1)实现Cloneable接口
 7  *                    (2)重写Object的clone方法
 8  */
 9 public class Mail implements Cloneable{
10     
11     private String name;
12     
13     private String context;
14     
15     private String title;
16     
17     private String address;
18 
19     
20     public Mail(String name, String context, String title, String address) {
21         super();
22         this.name = name;
23         this.context = context;
24         this.title = title;
25         this.address = address;
26     }
27 
28     
29     /**
30      * 克隆方法
31      */
32     @Override
33     protected Mail clone() throws CloneNotSupportedException {
34         Mail mail1=null;
35         mail1=(Mail) super.clone();
36         return mail1;
37     }
38 
39 
40     public String getName() {
41         return name;
42     }
43 
44     public void setName(String name) {
45         this.name = name;
46     }
47 
48     public String getContext() {
49         return context;
50     }
51 
52     public void setContext(String context) {
53         this.context = context;
54     }
55 
56     public String getTitle() {
57         return title;
58     }
59 
60     public void setTitle(String title) {
61         this.title = title;
62     }
63 
64     public String getAddress() {
65         return address;
66     }
67 
68     public void setAddress(String address) {
69         this.address = address;
70     }
71     
72     
73 }
View Code

相关文章: