2009年10月14日

          1.1 BUILDER生成器

          1、 意圖

          將一個復雜對象的構建和它的表示分離,使得同樣的構建過程可以創建不同的表示。

          構建是通過對生成器抽象接口的調用實現的。而構建出來的產品的類型(表示),是由具體的進行構建的生成器的子類的實例來決定的。這樣導向器只需要調用生成器的抽象接口生成產品,而具體生成什么樣的產品,則是根據導向器配置的具體的生成器實例相關。

          終于理解了它是如何把復雜對象的構建和它的表示分離的,也理解了為什么同樣的構建過程。

          2、 動機

          3、 適用性

          當創建復雜對象的算法應該獨立于該對象的組成以及他們的裝配方式時——對象的組成及裝配方式是生成器的抽象接口來表示的。而對象的創建的算法是有生成器的子類實現的。

          當構造過程必須允許被構造的對象有不同的表示時——也就是,同樣的構造過程,可以生成不同的產品。這里是通過配置導向器的生成器的子類實例來實現的。

          4、 結構

          wps_clip_image-372

          5、 參與者

          l Builder:為創建一個product對象的各個部件指定抽象接口。這些部件最終構成了product,而對這些抽象接口的調用,則是裝配product的操作,調用的次數,入參等不同,則最終生成的product也不同。product本身的構造過程可能會非常復雜。但是,這些復雜度對Director(導向者)是隱藏的。這些抽象的接口描述了產品的組成以及裝配方式。

          l ConcreteBuilder:實現Builder的接口以構造和裝配產品的各個部件;定義并明確它所創建的表示;提供一個檢索產品的接口。這個類實現了Builder的抽象接口,從而可以創建不同的表示,但是組成和裝配過程還是一樣的。

          l Director:構造一個使用Builder抽象接口的對象。更對象根據Builder的接口來裝配并生產產品。

          l Product:表示被構造的復雜的對象。ConcreteBuilder創建該產品的內部表示,并定義它的裝配過程;包含定義組成部件的類,包括將這些部件裝配成最終產品的接口。

          6、 協作

          l 客戶創建Director對象,并用它想要的Builder對象進行配置。

          l 一旦產品不僅被生成,導向器就會通知生成器。

          l 生成器處理導向器請求,并且將部件添加到該產品中。

          l 客戶從生成器中檢索產品。

          wps_clip_image-911

          7、 效果

          l 它使你可以改變一個產品的內部表示。Builder提供給Director的抽象接口可以使生成器隱藏這個產品的表示和內部結構。它同時也隱藏了該產品時如何裝配的。因為產品時通過抽象接口構造的,你改變該產品的內部表示時,所要做的只是定義一個新的生成器。

          l 它將構造代碼和表示代碼分開。Builder模式通過封裝一個復雜對象的創建和表示方式提高了對象的模塊性。每個ConcreteBuilder包含了創建和裝配一個特定產品的所有代碼。

          l 它可以使你對構造過程進行更精細的控制。

          8、 實現

          l 通常一個抽象的Builder類為導向者可能要求創建的每一個構件定義一個操作。這些操作缺省什么也不做。一個ConcreteBuilder類對它有興趣創建的構建重定義這些操作。

          l 裝配和構造接口:一般構造請求的結果只是被添加到產品中,特殊情況下,需要返回給導向器。

          l 產品沒有抽象類:一般他們沒有公共的部分。如果有也可以設置一個抽象類。

          l Builder中缺省的方法為空。

          9、 代碼示例

          class MazeBuilder {

          public:

              virtual void BuildMaze() { }//部件的構造方法

              virtual void BuildRoom(int room) { }

              virtual void BuildDoor(int roomFrom, int roomTo) { }

              virtual Maze* GetMaze() { return 0; }

          protected:

              MazeBuilder();

          };//MazeBuilder是生成器

          class StandardMazeBuilder : public MazeBuilder {

          public:

              StandardMazeBuilder();

          /*

          */

              virtual void BuildMaze();

              virtual void BuildRoom(int);

              virtual void BuildDoor(int, int);

          /*

          */

              virtual Maze* GetMaze();

          private:

              Direction CommonWall(Room*, Room*);

              Maze* _currentMaze;

          };//StandardMazeBuilder是ConcreteBuilder,提供部件的具體構造代碼

          Maze* MazeGame::CreateMaze (MazeBuilder& builder) {

              builder.BuildMaze();

              builder.BuildRoom(1);

              builder.BuildRoom(2);

              builder.BuildDoor(1, 2);

              return builder.GetMaze();

          }//CreateMaze是導向器,調用生成器的抽象接口完成產品的構造過程。

          //下面代碼描述產品的構造過程

          Maze* maze;//最終的產品

          MazeGame game;//Director,導航者

          StandardMazeBuilder builder;//ConcreteBuilder,實際的構造類

          game.CreateMaze(builder);//開始裝配

          maze = builder.GetMaze();//獲取裝配后的產品

          posted @ 2010-03-31 21:07 常高偉 閱讀(245) | 評論 (0)編輯 收藏

          1.1 ABSTRACT FACTORY 抽象工廠

          1、 意圖

          提供一個創建一系列相關或相互依賴對象的接口,而無需指定他們具體的類。

          2、 動機

          “客戶僅與抽象定義的接口交互,而不使用特定的具體類的接口?!?

          這里的主要的思想是封裝對象的創建的過程??蛻舳丝梢圆恍枰谰唧w要創建那些對象,而只需要知道創建某一系列的對象所用到的“工廠對象”即可。

          3、 適用性

          一個系統要獨立于它的產品的創建、組合和表示時。 

          一個系統要由多個產品系列中的一個來配置時。 

          當你要強調一系列相關的產品對象的設計以便進行聯合使用時。 

          當你提供一個產品類庫,而只想顯示它們的接口而不是實現時。 

          4、 結構

          wps_clip_image-278

          5、 參與者

          AbstractFactory:創建一系列對象的抽象類。

          ConcreteFactory:實現具體創建產品對象的操作。

          AbstractProduct:為一類產品對象聲明一個接口。

          ConcreteProduct:定義一個被相應的具體工廠創建的對象;實現AbstractProduct接口。

          Client:僅使用AbstractFactory和AbstractProduct類聲明的接口。

          6、 協作

          在運行時刻,創建一個ConcreteFactory實例,它創建具有特定實現的對象。為創建不同的對象,客戶應使用不同的具體工廠。

          AbstractFactory將具體對象的創建延遲到它的子類ConcreteFactory中。

          7、 效果

          1) 它分離了具體的類:一個工廠封裝創建產品的責任和過程,它將客戶和類的實現分離??蛻敉ㄟ^抽象接口操作實例。產品的類名也在具體工廠實現中分離,他們不出現在客戶代碼中。

          2) 它使得易于交互產品系列。

          3) 它有利于產品的一致性。

          4) 難于支持新的種類。

          posted @ 2010-03-03 20:27 常高偉 閱讀(196) | 評論 (0)編輯 收藏

          1.1 設計模式怎樣解決設計問題

          1.1.1 尋找合適的對象

          面向對象設計最困難的部分是將系統分解為對象的集合。

          設計的許多對象來源于現實世界的分析模型,這里和領域驅動設計有點關聯。分析所得到的類,很多事現實中并不存在的類。這是抽象的結果。設計中的抽象對于產生靈活的設計至關重要。就像我設計的一個流程調度模型。

          1.1.2 決定對象的粒度

          記筆記可以讓我達到沉流的狀態。

          1.1.3 指定對象接口
          1.1.4 描述對象實現

          OMT表示法:

          1、 對象:最上面的黑體表示類名,下面依次是操作,數據。

          wps_clip_image-219

          2、 實例化:虛線箭頭表示一個類實例化另外一個對象。

          wps_clip_image-245

          3、 繼承:豎線和三角表示繼承關系。

          wps_clip_image-263

          4、 抽象類:類名以黑體斜體表示,操作也用斜體表示。

          5、 引用

          wps_clip_image-293

          箭頭加黑點表示一個類引用另外一個類。

          重點:

          1、 類的繼承和接口繼承的比較

          對象的類和對象的類型的區別:

          對象的類定義了對象是怎樣實現的,同時也定義了對象內部狀態和操作的實現。對象的類型只與它的接口有關。一個對象可以由多個類型(支持多個接口),不同類的對象可以有相同的類型。

          類和類型緊密相連,類定義了對象的操作,也定義了對象的類型。

          類的繼承和接口的繼承的差別:

          c++中接口繼承接近于公有繼承純抽象類。純實現繼承或純類繼承接近于私有繼承。

          2、 對接口編程,而不是對實現編程——面向對象設計的第一個原則

          1.1.5 運用復用機制

          1、 繼承和組合的比較

          繼承是一種白箱復用,父類的內部細節對子類可見。

          對象組合彼此不知道對方內部細節,成為黑箱復用。

          繼承的優缺點:

          1) 子類可以直接重定義父類的操作。

          2) 編譯時刻決定了,無法在運行期間更改。

          3) 子類要知道父類的實現細節,這樣就部分破壞了封裝性。子類和父類依賴過于緊密,父類的某些變化必然導致子類的變化。開發過程中遇到過類似的問題。這種依賴,限制了靈活性以及復用性。比如,服務體系中經常出現這樣的問題,導致代碼拷貝。

          組合(通過獲得對象的引用而在運行時刻動態的定義)的優缺點:

          1) 對象間通過接口彼此交互。

          2) 對象只能通過接口訪問,不要也不能知道對方細節,這樣不會破壞封裝性。

          3) 運行時刻可以使用另外一個對象替換這個對象,提高了靈活性。

          4) 對象的實現基于接口編寫,所以實現上存在較少的依賴關系。

          5) 優先使用組合有助于保持每個類被封裝,并被集中在單個任務上,提高整體內聚性。類和類的層次都維持一個較小的規模,

          6) 基于對象組合的設計會有更多的對象(而又較少的類),且系統的行為依賴于對象間的關系而不是定義在某個類的內部。

          理想的情況下,應該通過組合原有構件實現新的功能,而不是創建新的構件。

          面向對象設計的第二個原則:優先使用對象組合,而不是類繼承。

          2、 委托

          委托時一種組合方法,它是組合具有與繼承同樣的能力。

          委托的主要優點在于它便于在運行時刻組合對象操作,以及更改操作的組合方式。它是軟件更加的靈活。

          和其他的技術方案相同,它也存在不足之處:增加了軟件的復雜度——動態的,高度參數化的軟件比靜態的軟件更難于理解。

          3、 繼承和參數化類型的比較

          1.1.6 關聯運行時刻的結構和編譯時刻的結構
          1.1.7 設計應支持變化

          設計應該支持變化——所說的是,一個設計方案,對變化要有一定的適應性,即封裝變化。

          變化是導致重新設計的原因。設計要對一定范圍內的變化友好。

          4、 

          對于程序的分層設計,對于處于同一分層的模塊,對外應保持一定的抽象,并且,使用同種類型的通信協議。

          posted @ 2010-03-03 20:26 常高偉 閱讀(442) | 評論 (0)編輯 收藏

          1.1 變量存儲域

          1.1.1 一個示例

          pang123hui首先提供了一個網上流傳的學習代碼示例:

          int a = 0; //全局區 

          void main() 

          {

          int b; //棧 

          char s[] = “abc”; //s在棧,abc在文字常量區 

          char *p1,*p2; //棧 

          char *p3 = "123456"; //123456在常量區,p3在棧上 

          static int c =0; //全局區 

          p1 = (char *)malloc(10); //p1在棧,分配的10字節在堆 

          p2 = (char *)malloc(20); //p2在棧,分配的20字節在堆 

          strcpy(p1, "123456"); //123456放在常量區 

          }

          這個代碼示例中出現了“全局區”,“棧”,“文字常量區”,“堆”等詞語。為了統一,我們使用《C專家編程》中的說法:堆棧段,BSS段,數據段,文本段。

          各個段的作用如下:

          1、 文本段:包含程序的指令,它在程序的執行過程中一般不會改變。

          2、 數據段:包含了經過初始化的全局變量和靜態變量,以及他們的值。

          3、 BSS段:包含未經初始化的全局變量和靜態變量。

          4、 堆棧段:包含了函數內部聲明的局部變量。

          當然,上面段的作用不僅于此,具體的作用會在下面的知識點中介紹。

          1.1.2 通過代碼測試變量的存儲位置

          Linux下可以通過系統命令“size”查看可以執行程序各個段的大小。但是,可執行程序中的段結構和運行中程序在內存中的段結構并不完全相同,但是有一定的映射關系。具體如下圖所示(圖片信息來自《C專家編程》):

          wps_clip_image-696

          下面通過代碼示例和“size”來研究變量的存儲區域。

          test.c

          int main()

          {

          return 1;

          }

          編譯,并且查看可執行程序各個段的大?。?

          wps_clip_image-779

          更改test.c:

          int g_data;

          int main()

          {

          return 1;

          }

          編譯,并且查看可執行程序各個段的大小:

          wps_clip_image-849

          可以發現,文本段,數據段都沒有發送變化,而BSS段增加了4個字節。

          結論1:未初始化的全局變量保存在BSS段中

          繼續:

          int g_data = 1;

          int main()

          {

          return 1;

          }

          編譯:

          wps_clip_image-958

          可以發現,BSS段和文本段相同,而數據段增加了4個字節。

          結論2:經過初始化的全局變量保存在數據段中

          繼續:

          int main()

          {

          static int g_data;

          return 1;

          }

          編譯:

          wps_clip_image-1066

          可以發現,文本段,數據段都沒有發送變化,而BSS段增加了4個字節。

          結論3:未初始化的靜態變量保存在BSS段中

          繼續:

          int main()

          {

          static int g_data = 1;

          return 1;

          }

          編譯:

          wps_clip_image-1183

          可以發現,BSS段和文本段相同,而數據段增加了4個字節。

          結論4:經過初始化的靜態變量保存在數據段中

          繼續:

          int main()

          {

          int i_data = 1;

          return 1;

          }

          編譯:

          wps_clip_image-1288

          可以發現,BSS段和和數據段相同,而文本段增加了16個字節。局部變量會在執行的時候在堆棧段中生成,函數執行完畢后釋放。

          結論5:函數內部聲明的局部變量保存在堆棧段中

          繼續:

          const int g_data = 1;

          int main()

          {

          return 1;

          }

          編譯:

          wps_clip_image-1430

          把全局變量定義為“const”后,也許你會感到奇怪,怎么BSS段和數據段都沒有發生變化,而文本段卻增加了4個字節。

          結論6:const修飾的全局變量保存在文本段中

          那么,const的局部變量?

          繼續:

          int main()

          {

          const int i_data = 1;

          return 1;

          }

          編譯:

          wps_clip_image-1587

          結論7:const修飾的局部變量保存在堆棧段中

          繼續:

          char *pstr = "";

          int main()

          {

          return 1;

          }

          編譯:

          wps_clip_image-1666

          在做一下更改:

          char *pstr = "123456789";

          int main()

          {

          return 1;

          }

          編譯:

          wps_clip_image-1733

          可以發現,前后數據段和BSS段大小均未發生變化,而文本段增加了9個字節。

          結論8:字符串常量保存在文本段中

          1.1.3 結論

          1、 經過初始化的全局變量和靜態變量保存在數據段中。

          2、 未經初始化的全局變量和靜態變量保存在BSS段。

          3、 函數內部聲明的局部變量保存在堆棧段中。

          4、 const修飾的全局變量保存在文本段中,const修飾的局部變量保存在堆棧段中。

          5、 字符串常量保存在文本段中。

          1.1.4 擴展閱讀

          《C專家編程》第6章——詳細介紹各個段的作用。

          posted @ 2010-03-03 02:38 常高偉 閱讀(299) | 評論 (0)編輯 收藏

          讀S計劃的理念

          自助、互助,共同進步!

           

          讀S計劃的初衷

          現在有很多學習方式,搜索引擎、論壇、博客,qq群等等,那么我這樣的計劃還有存在的必要么?這個計劃的獨特之處在哪里?

          讀S計劃的獨特之處不在于其學習內容和方式,學習的內容我們可以根據實際情況調整,可以由多個人同時引導多個學習方向,這些都不是程式化的,也不是重點。

          讀S計劃的獨特之處在于其理念:致力于形成一種有計劃、有組織,強調互動、互助和共同進步的學習模式和氛圍。讀S計劃不是一個單純的興趣小組,我們會按照計劃不斷的切換話題。讀S計劃也不是提問的好地方,在每個階段,我們都有限定的討論范圍,所以無關的問題很容易被忽略。讀S計劃希望多數人以積極的心態參與進來,更多的討論、研究和貢獻您的想法,而不是被動的接受和看,我們不希望將學習計劃做成課堂模式,我們希望做成項目的模式 。讀S計劃致力于將信息以信息本身進行聚合,而不是以人進行聚合,因為學習計劃在不斷推進,所以不存在永遠的權威人士,但知識本身是客觀、中立的、權威的。

           

          共建新型技術社區

          建立新型的、關系緊密的、以知識體系為軸、強調經驗積累與分享的的技術社區。

           

          更深入了解此計劃,可以閱讀:

          《技術族譜 之 讀S計劃:讓我們一起快樂學習》

          《準備啟動一個開源項目 - 技術族譜 - 先期利用Goolge云計算平臺》

          《關于“讀S計劃”的聊天記錄:統一理念,確定目前的工作》

          《授人以“魚”,不如授人以“漁”,放棄一個目標,設定另一個目標》

          期待你加入我們的群組:http://hi.csdn.net/space-mtag-tagid-37.html

          posted @ 2009-10-14 21:43 常高偉 閱讀(212) | 評論 (0)編輯 收藏


          posts - 19, comments - 0, trackbacks - 0, articles - 0

          Copyright © 常高偉

          主站蜘蛛池模板: 温泉县| 万载县| 芜湖市| 遂平县| 偃师市| 玉龙| 赤水市| 米林县| 元朗区| 绍兴县| 临邑县| 保靖县| 荥经县| 岑巩县| 禄丰县| 扎囊县| 长宁县| 贡嘎县| 罗田县| 郁南县| 通州市| 新建县| 炎陵县| 襄垣县| 田东县| 沭阳县| 华池县| 诏安县| 治多县| 固镇县| 营山县| 酒泉市| 二连浩特市| 浦东新区| 榆中县| 玉屏| 讷河市| 永康市| 巴东县| 四川省| 乐业县|