设计模式学习之--原型模式(Prototype)

原型模式:

1、定义:原型模式就是通过一个原型对象来表明要创建的对象类型,然后用复制这个对象的方法来创建更痛类型的对象。

2、原理:有两部分组成,抽象原型和具体原型。

3、使用时机:系统需要 创建吃的对象是动态加载的,而且产品具有一定层次时,可以考虑使用原型模式。

1>当要实例化的类是在运行时刻指定时,例如,通过动态装载;

2>或者为了避免创建一个与产品类层次平行的工厂类层次时;

3>或者当一个类的实例只能有几个不同状态组合中的一种时。

4>建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。

4、效果:

1>可以再运行时刻增加和删除产品。

2>可以通过改变值来指定产品。

3>可以通过改变结构来指定新对象。

4>减少子类的构造

5>可以用类动态配置应用。

5、实现:

1>使用一个原型管理器

2>实现克隆操作(浅拷贝和深拷贝)

3>初始化克隆对象。

6、使用原型模式的意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

7、解决的问题:

比如有一个对象,在某一时刻该对象中已经包含了一些有效的值,此时可能会需要一个和该对象完全相同的新对象,并且此后对新对象的任何改动都不会影响到原来对象中的值,也就是说新对象与原来的对象是两个独立的对象,但新对象的初始值是由原来的对象确定的。

Clone:

赋值创建对象:

1>java中赋值创建对象是可以实现对象的重用的,但是新对象和原对象是同一个引用;如果修改其中的一个对象的值,则另外的一个对象也会发生改变。

2>使用clone方法会返回对象的一个拷贝,这样一来,如果修改一个对象的值,则另外的对象不会发生改变的。


原型模式UML图:


UML

请注意,在 这边 Cloneable 并非指 Java 中的 java.lang.Cloneable ,而是指支持原型复制 的对象,必须实作之公开协议。

同的语言可能提供不同程 度支持之对象复制技术,以 Java 而言, java.lang.Object 本身即定义有 clone() 方法,因此所有的对象 基本上 皆具自我复制之能力,不 过真正要让对象支持复制,则对象必须实作 java.lang.Cloneable 这个标示接口( Tag interface )。


原型模式浅拷贝与 原型模式深度拷贝:

看看这样一个示例:有个类(DogClone)实现了Java的Cloneable接口,也实现了Object的clone()方法,它持有另一个 没有实现Cloneable接口并且没有复写Object的clone()方法的引用(Dog)。如果Dog同时实现了clone()方法也实现了 Cloneable接口,在对DogClone做科隆操作的时候会不会影响dog的值呢?

 

Java代码   收藏代码
  1. package  org.bestupon.prototype.copy;  
  2. /**  
  3.  * 同实现了克隆方法的类和实现克隆方法的类做比较  
  4.  * @author bestupon  
  5.  * 浅拷贝Dog  
  6.  */   
  7. public   class  Dog {  
  8.     /**  
  9.      * 狗腿条数  
  10.      */   
  11.     public   int  legCounts;  
  12.   
  13.     public  Dog( int  legCounts) {  
  14.         this .legCounts = legCounts;  
  15.     }  
  16.     /**  
  17.      * 改变狗的腿数量  
  18.      */   
  19.     public   void  changeLegCounts(){  
  20.         this .legCounts *= 2 ;  
  21.     }  
  22.     public  String toString () {  
  23.         return  Integer.toString( this .legCounts);  
  24.     }  
  25. }  

 

 

Java代码   收藏代码
  1. package  org.bestupon.prototype.clone;  
  2. /**  
  3.  * 该类是没有实现克隆方法的类和实现克隆方法的类做比较  
  4.  * @author bestupon  
  5.  * 深度拷贝用例  
  6.  */   
  7. public   class  Dog  implements  Cloneable{  
  8.     /**  
  9.      * 狗腿条数  
  10.      */   
  11.     public   int  legCounts;  
  12.   
  13.     public  Dog( int  legCounts) {  
  14.         this .legCounts = legCounts;  
  15.     }  
  16.     /**  
  17.      * 改变狗的腿数量  
  18.      */   
  19.     public   void  changeLegCounts(){  
  20.         this .legCounts *= 2 ;  
  21.     }  
  22.       
  23.     @Override   
  24.     public  Dog clone()  throws  CloneNotSupportedException {  
  25.         return  (Dog) super .clone();  
  26.     }  
  27.     public  String toString () {  
  28.         return  Integer.toString( this .legCounts);  
  29.     }  
  30. }  

 

 

Java代码   收藏代码
  1. package  org.bestupon.prototype.copy;  
  2.   
  3. public   class  DogClone  implements  Cloneable {  
  4.     /**  
  5.      * 狗腿条数  
  6.      */   
  7.     public   int  legCounts;  
  8.     /**  
  9.      * 初始化一个狗  
  10.      */   
  11.     Dog dog = new  Dog( 4 );  
  12.     @Override   
  13.     protected  DogClone clone()  throws  CloneNotSupportedException {  
  14.         return  (DogClone) super .clone();  
  15.     }  
  16.       
  17. }  

 

 

Java代码   收藏代码
  1. <span style= "white-space: normal;" > <span style= "white-space: pre;" > package  org.bestupon.prototype.copy;</span></span>  
  2. /** 浅拷贝  
  3.  * @author bestupon  
  4.  *  
  5.  */   
  6. public   class  Client {  
  7.     public   static   void  main(String args [])  throws  CloneNotSupportedException {  
  8.         DogClone dogClone = new  DogClone();  
  9.         dogClone.legCounts = 3 ;  
  10.         System.out.println("原来的克隆狗腿数量:" +dogClone.legCounts);  
  11.         System.out.println("原来的普通狗腿的数量:" +dogClone.dog); //Dog的toString方法返回的值。   
  12.           
  13.         DogClone dogClone1 = (DogClone)dogClone.clone();  
  14.         dogClone1.legCounts=2  ;  
  15.           
  16.          Dog dog = dogClone1.dog;  
  17.          dog.changeLegCounts();  
  18.          System.out.println("克隆后原来狗腿数量:" +dogClone.legCounts);  
  19.          /**  
  20.           * 出现的结果是:8  
  21.           * 原因很简单就是dog是一个引用,改变一个对象的话,会改变另一个对象。  
  22.           */   
  23.          System.out.println("克隆后原来普通狗的数量:" + dogClone.dog);  
  24.          System.out.println("克隆后克隆狗腿的数量:" + dogClone1.legCounts);  
  25.          /**  
  26.           *改变源:改变了自身dogClone.dog,影像了对象dogClone.dog 的值,  
  27.           */   
  28.          System.out.println("克隆后普通狗的数量:" + dogClone1.dog);  
  29.           
  30.     }  
  31. }  
 

两次运行结果:


没有实现Cloneable接口和clone()方法结果:

 

Java代码   收藏代码
  1. 原来的克隆狗腿数量: 3   
  2. 原来的普通狗腿的数量:4   
  3. 克隆后原来狗腿数量:3   
  4. 克隆后原来普通狗的数量:8   
  5. 克隆后克隆狗腿的数量:2   
  6. 克隆后普通狗的数量:8   
 

 

实现了Cloneable接口和clone()方法结果:

 

Java代码   收藏代码
  1. 原来的克隆狗腿数量: 3   
  2. 原来的普通狗腿的数量:4   
  3. 克隆后原来狗腿数量:3   
  4. 克隆后原来普通狗的数量:4   
  5. 克隆后克隆狗腿的数量:2   
  6. 克隆后普通狗的数量:8   


 同样的客户端为什么会有不同的结果呢?这就是所谓的浅拷贝和深拷贝的为题.

 

分析:

浅拷贝: DogClone类中的legCounts属性被科隆了,因为对科隆后的对象进行修改时,没有改变原来对象的值,其原因是实现了接口和方法,而DogClone,Dog对象 dog没有被科隆,而在修改科隆后的对象时,会改变原来对象的值。

如果要是都实现了接口和方法,就实现了深度科隆,不会影响远对象的值。

 

应用:

 不是所有的对象都是能实现深度科隆的,例如:StringBuffer就没有重载Clone()方法,而且StringBuffer还是一个final类,所以其不能自动实现深度科隆。


在Spring中.深度科隆是应用广泛的。在实体模型上面有这样一个注 解:@Component("lawsuitArchive") @scope("prototype"),表明在别的地方应用的时候,是引用其原型,同时Entity也要实现Cloneable接口和复写 clone()方法。因为原型在初始化的时候就已经创建了一部分有价值的东西,减少容器的压力,而在别的地方,例如action中引用该对象的时候,直接 可以使用@Resource(name="lawsuitArchive")引用对象,Spring会自动的装配好你想要的对象。

资料下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值