GOF设计模式学习笔记(二)---Prototype模式

Posted on 2007-05-14 11:17 久城 阅读(2520) 评论(5)  编辑  收藏 所属分类: GOF设计模式
老板说:“给我盖一座大楼。”

工程师说:“盖什么样的大楼呢?”

老板指着身后的一座楼说:“和那个一模一样的。”

从老板的角度来讲,他采用的就是,Prototype模式,即原型模式。否则,他需要再花费一些时间和工程师一点一点的探讨关于大楼的一些设计问题。

所谓的原型模式,就是用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

JAVA的Object.clone()的存在,使得这个模型的学习变得简单了许多。

一.搭桥过河
过河是一门大学问

首先研究一下JAVA的clone技术。

我理解的很简单,无非是把一个对象进行复制粘贴。那么,来看一下JAVA语言中是如何来实现的这个步骤的。我们依次需要知道以下这些事。

1.Object对象中有一个clone()方法。而且是protected。

2.继承于Object的类一般都可以实现这个方法(有特殊的,比如StringBuffer等,官方定的,不去研究它)。

3.想被clone的对象需要实现接口Cloneable。如果此对象的类不能实现接口Cloneable,则会抛出CloneNotSupportedExcetion。

4.所有的数组都被视为实现接口Cloneable。

5.clone分为浅clone(又称影子clone)和深clone。

6.Object类本身不实现接口Cloneable,所以在类为Object的对象上调用clone方法,将会导致在运行时抛出异常。

首先来看一个能够实现clone类的小例子。
//本文代码参考于http://blog.csdn.net/tiewen/archive/2005/08/05/446301.aspx
class CloneClass implements Cloneable {
    
public int aInt;

    
public Object clone() {
        CloneClass o 
= null;
        
try {
            o 
= (CloneClass) super.clone();
        }
 catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

        
return o;
    }

}

至于浅clone和深clone,无非就是一个程度问题。再来看一个例子。
class UnCloneA {
    
private int i;

    
public UnCloneA(int ii) {
        i 
= ii;
    }


    
public void doublevalue() {
        i 
*= 2;
    }


    
public String toString() {
        
return Integer.toString(i);
    }

}


class CloneB implements Cloneable {
    
public int aInt;

    
public UnCloneA unCA = new UnCloneA(111);

    
public Object clone() {
        CloneB o 
= null;
        
try {
            o 
= (CloneB) super.clone();
        }
 catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

        
return o;
    }

}


class CloneMain {
    
public static void main(String[] a) {
        CloneB b1 
= new CloneB();
        b1.aInt 
= 11;
        System.out.println(
"before clone,b1.aInt = " + b1.aInt);
        System.out.println(
"before clone,b1.unCA = " + b1.unCA);
        CloneB b2 
= (CloneB) b1.clone();
        b2.aInt 
= 22;
        b2.unCA.doublevalue();
        System.out.println(
"=================================");
        System.out.println(
"after clone,b1.aInt = " + b1.aInt);
        System.out.println(
"after clone,b1.unCA = " + b1.unCA);
        System.out.println(
"=================================");
        System.out.println(
"after clone,b2.aInt = " + b2.aInt);
        System.out.println(
"after clone,b2.unCA = " + b2.unCA);
    }

}


输出结果为:
/** RUN RESULT:
before clone,b1.aInt = 11
before clone,b1.unCA = 111
=================================
after clone,b1.aInt = 11
after clone,b1.unCA = 222
=================================
after clone,b2.aInt = 22
after clone,b2.unCA = 222
*/

可见,当执行clone这个动作的时候,系统首先开辟一个和它一样的空间。然后分别对其内容进行复制。复制过程中,如果是基本类型,没什么说的,直接把值复制过来。如果不是基本类型,复制的则是该类型对象的引用。

这样的clone就是所谓的浅clone。那很显然,如果上面复制的过程中,对于非基本类型实现的不是一个引用复制,而是创建一个新的一样的对象(其实也是一个clone步骤),那么就是所谓的深clone。对于深度克隆只不过是clone的一种扩展,还有N深clone等等。对于这些,和我们要研究的原型模式没有多少关系。不想去研究。


关于JAVA的clone技术,对我来说,理解这些就够了。其它的,就是进一步的扩展及应用。

二.以长克短
什么时候会想到用原型模式呢


这个我们学习任何一项技术都要问自己的问题。


要用它,就要知道它的优点。合理的利用它的优点来为我们服务。做人也一样,不要总拿自己的短处去比别人的长处。要知道,每个人都是不一样的,每个人都有自己的长处和短处。这就是以长克短。

JAVA中的clone方法,其实现是native的。这也就意味着它的执行效率是远高于new一个新对象的。所以,当需要生成大量相似对象的时候,可以考虑下应用clone,也就是原形模式。

我的项目经验几乎为0,单纯从理解的角度去想的。

至于其它的应用,还有待前辈们指点。我再不断补充。



欢迎来访!^.^!
本BLOG仅用于个人学习交流!
目的在于记录个人成长.
所有文字均属于个人理解.
如有错误,望多多指教!不胜感激!

Feedback

# re: GOF设计模式学习笔记(二)---Prototype模式  回复  更多评论   

2007-05-14 11:46 by 刘甘泉
进行clone时候要考虑object的调用修改问题,如果不对object进行修改的话,浅clone是很好的,如果要修改的话会引起问题
具体好像TIJ(thinking in java)有讲,effective java也有讲

# re: GOF设计模式学习笔记(二)---Prototype模式  回复  更多评论   

2007-05-14 13:23 by 久城
@刘甘泉
多谢指教。在网上看到一些文章也是提醒要注意修改时的操作。
至于修改什么还不是很清楚。
我想,在应用深度clone的时候,需要重写Object类中的clone方法,对于基本类型就不用考虑了,对于非基本类型,需要手动的进行“复制”。大家所说的“会引起问题”是出自这里吧?这个“复制”如果也是一个clone,就需要考虑这个非基本类型对象是否允许被clone,这个clone操作是否也是深度clone等问题。
象StringBuffer这样的,不可修改的类。就需要手动的“COPY IT!”
还有一些就需要用到迭代方法,来迭代执行clone方法,达到N深度clone的效果。
这些我还没有深入的研究。感觉实践中用的机会很少。

# re: GOF设计模式学习笔记(二)---Prototype模式  回复  更多评论   

2007-05-14 16:20 by 刘甘泉
@久城
这个其实就是值与引用的问题,在浅拷贝的时候都是只进行引用的拷贝,基本类型就是直接拷贝,所以在修改的时候,基本类型的修改是没有问题的,而其他的对象的修改的时候就会修改到堆中的数据,即引用指向的数据。
对象里面除基本类型都是存储的引用,即c++的指针指向地址

# re: GOF设计模式学习笔记(二)---Prototype模式  回复  更多评论   

2007-05-14 19:07 by 久城
@刘甘泉
了解了!^.^!

# re: GOF设计模式学习笔记(二)---Prototype模式  回复  更多评论   

2007-10-07 16:42 by wanjinyou
看到两位的讨论,很有收获,呵呵

只有注册用户登录后才能发表评论。


网站导航:
 

Copyright © 久城