老板說:“給我蓋一座大樓。”

          工程師說:“蓋什么樣的大樓呢?”

          老板指著身后的一座樓說:“和那個(gè)一模一樣的。”

          從老板的角度來講,他采用的就是,Prototype模式,即原型模式。否則,他需要再花費(fèi)一些時(shí)間和工程師一點(diǎn)一點(diǎn)的探討關(guān)于大樓的一些設(shè)計(jì)問題。

          所謂的原型模式,就是用原型實(shí)例指定創(chuàng)建對(duì)象的種類,并且通過拷貝這些原型創(chuàng)建新的對(duì)象。

          JAVA的Object.clone()的存在,使得這個(gè)模型的學(xué)習(xí)變得簡單了許多。

          一.搭橋過河
          過河是一門大學(xué)問

          首先研究一下JAVA的clone技術(shù)。

          我理解的很簡單,無非是把一個(gè)對(duì)象進(jìn)行復(fù)制粘貼。那么,來看一下JAVA語言中是如何來實(shí)現(xiàn)的這個(gè)步驟的。我們依次需要知道以下這些事。

          1.Object對(duì)象中有一個(gè)clone()方法。而且是protected。

          2.繼承于Object的類一般都可以實(shí)現(xiàn)這個(gè)方法(有特殊的,比如StringBuffer等,官方定的,不去研究它)。

          3.想被clone的對(duì)象需要實(shí)現(xiàn)接口Cloneable。如果此對(duì)象的類不能實(shí)現(xiàn)接口Cloneable,則會(huì)拋出CloneNotSupportedExcetion。

          4.所有的數(shù)組都被視為實(shí)現(xiàn)接口Cloneable。

          5.clone分為淺clone(又稱影子clone)和深clone。

          6.Object類本身不實(shí)現(xiàn)接口Cloneable,所以在類為Object的對(duì)象上調(diào)用clone方法,將會(huì)導(dǎo)致在運(yùn)行時(shí)拋出異常。

          首先來看一個(gè)能夠?qū)崿F(xiàn)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,無非就是一個(gè)程度問題。再來看一個(gè)例子。
          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);
              }

          }


          輸出結(jié)果為:
          /** 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
          */

          可見,當(dāng)執(zhí)行clone這個(gè)動(dòng)作的時(shí)候,系統(tǒng)首先開辟一個(gè)和它一樣的空間。然后分別對(duì)其內(nèi)容進(jìn)行復(fù)制。復(fù)制過程中,如果是基本類型,沒什么說的,直接把值復(fù)制過來。如果不是基本類型,復(fù)制的則是該類型對(duì)象的引用。

          這樣的clone就是所謂的淺clone。那很顯然,如果上面復(fù)制的過程中,對(duì)于非基本類型實(shí)現(xiàn)的不是一個(gè)引用復(fù)制,而是創(chuàng)建一個(gè)新的一樣的對(duì)象(其實(shí)也是一個(gè)clone步驟),那么就是所謂的深clone。對(duì)于深度克隆只不過是clone的一種擴(kuò)展,還有N深clone等等。對(duì)于這些,和我們要研究的原型模式?jīng)]有多少關(guān)系。不想去研究。


          關(guān)于JAVA的clone技術(shù),對(duì)我來說,理解這些就夠了。其它的,就是進(jìn)一步的擴(kuò)展及應(yīng)用。

          二.以長克短
          什么時(shí)候會(huì)想到用原型模式呢


          這個(gè)我們學(xué)習(xí)任何一項(xiàng)技術(shù)都要問自己的問題。


          要用它,就要知道它的優(yōu)點(diǎn)。合理的利用它的優(yōu)點(diǎn)來為我們服務(wù)。做人也一樣,不要總拿自己的短處去比別人的長處。要知道,每個(gè)人都是不一樣的,每個(gè)人都有自己的長處和短處。這就是以長克短。

          JAVA中的clone方法,其實(shí)現(xiàn)是native的。這也就意味著它的執(zhí)行效率是遠(yuǎn)高于new一個(gè)新對(duì)象的。所以,當(dāng)需要生成大量相似對(duì)象的時(shí)候,可以考慮下應(yīng)用clone,也就是原形模式。

          我的項(xiàng)目經(jīng)驗(yàn)幾乎為0,單純從理解的角度去想的。

          至于其它的應(yīng)用,還有待前輩們指點(diǎn)。我再不斷補(bǔ)充。



          歡迎來訪!^.^!
          本BLOG僅用于個(gè)人學(xué)習(xí)交流!
          目的在于記錄個(gè)人成長.
          所有文字均屬于個(gè)人理解.
          如有錯(cuò)誤,望多多指教!不勝感激!

          Feedback

          # re: GOF設(shè)計(jì)模式學(xué)習(xí)筆記(二)---Prototype模式  回復(fù)  更多評(píng)論   

          2007-05-14 11:46 by 劉甘泉
          進(jìn)行clone時(shí)候要考慮object的調(diào)用修改問題,如果不對(duì)object進(jìn)行修改的話,淺clone是很好的,如果要修改的話會(huì)引起問題
          具體好像TIJ(thinking in java)有講,effective java也有講

          # re: GOF設(shè)計(jì)模式學(xué)習(xí)筆記(二)---Prototype模式  回復(fù)  更多評(píng)論   

          2007-05-14 13:23 by 久城
          @劉甘泉
          多謝指教。在網(wǎng)上看到一些文章也是提醒要注意修改時(shí)的操作。
          至于修改什么還不是很清楚。
          我想,在應(yīng)用深度clone的時(shí)候,需要重寫Object類中的clone方法,對(duì)于基本類型就不用考慮了,對(duì)于非基本類型,需要手動(dòng)的進(jìn)行“復(fù)制”。大家所說的“會(huì)引起問題”是出自這里吧?這個(gè)“復(fù)制”如果也是一個(gè)clone,就需要考慮這個(gè)非基本類型對(duì)象是否允許被clone,這個(gè)clone操作是否也是深度clone等問題。
          象StringBuffer這樣的,不可修改的類。就需要手動(dòng)的“COPY IT!”
          還有一些就需要用到迭代方法,來迭代執(zhí)行clone方法,達(dá)到N深度clone的效果。
          這些我還沒有深入的研究。感覺實(shí)踐中用的機(jī)會(huì)很少。

          # re: GOF設(shè)計(jì)模式學(xué)習(xí)筆記(二)---Prototype模式  回復(fù)  更多評(píng)論   

          2007-05-14 16:20 by 劉甘泉
          @久城
          這個(gè)其實(shí)就是值與引用的問題,在淺拷貝的時(shí)候都是只進(jìn)行引用的拷貝,基本類型就是直接拷貝,所以在修改的時(shí)候,基本類型的修改是沒有問題的,而其他的對(duì)象的修改的時(shí)候就會(huì)修改到堆中的數(shù)據(jù),即引用指向的數(shù)據(jù)。
          對(duì)象里面除基本類型都是存儲(chǔ)的引用,即c++的指針指向地址

          # re: GOF設(shè)計(jì)模式學(xué)習(xí)筆記(二)---Prototype模式  回復(fù)  更多評(píng)論   

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

          # re: GOF設(shè)計(jì)模式學(xué)習(xí)筆記(二)---Prototype模式  回復(fù)  更多評(píng)論   

          2007-10-07 16:42 by wanjinyou
          看到兩位的討論,很有收獲,呵呵

          Copyright © 久城

          主站蜘蛛池模板: 宁夏| 巩义市| 河西区| 屯昌县| 嘉鱼县| 宜都市| 边坝县| 普安县| 随州市| 湘潭县| 昭苏县| 泗水县| 琼中| 阳高县| 胶州市| 黄龙县| 台南县| 柳江县| 黄平县| 乳山市| 太谷县| 纳雍县| 和龙市| 克山县| 德昌县| 漳州市| 肃宁县| 远安县| 叶城县| 阿巴嘎旗| 辛集市| 惠水县| 富锦市| 宁阳县| 安多县| 华亭县| 乐亭县| 沙田区| 德安县| 周口市| 沙坪坝区|