2010年3月3日

          1.1 BUILDER生成器

          1、 意圖

          將一個(gè)復(fù)雜對(duì)象的構(gòu)建和它的表示分離,使得同樣的構(gòu)建過(guò)程可以創(chuàng)建不同的表示。

          構(gòu)建是通過(guò)對(duì)生成器抽象接口的調(diào)用實(shí)現(xiàn)的。而構(gòu)建出來(lái)的產(chǎn)品的類(lèi)型(表示),是由具體的進(jìn)行構(gòu)建的生成器的子類(lèi)的實(shí)例來(lái)決定的。這樣導(dǎo)向器只需要調(diào)用生成器的抽象接口生成產(chǎn)品,而具體生成什么樣的產(chǎn)品,則是根據(jù)導(dǎo)向器配置的具體的生成器實(shí)例相關(guān)。

          終于理解了它是如何把復(fù)雜對(duì)象的構(gòu)建和它的表示分離的,也理解了為什么同樣的構(gòu)建過(guò)程。

          2、 動(dòng)機(jī)

          3、 適用性

          當(dāng)創(chuàng)建復(fù)雜對(duì)象的算法應(yīng)該獨(dú)立于該對(duì)象的組成以及他們的裝配方式時(shí)——對(duì)象的組成及裝配方式是生成器的抽象接口來(lái)表示的。而對(duì)象的創(chuàng)建的算法是有生成器的子類(lèi)實(shí)現(xiàn)的。

          當(dāng)構(gòu)造過(guò)程必須允許被構(gòu)造的對(duì)象有不同的表示時(shí)——也就是,同樣的構(gòu)造過(guò)程,可以生成不同的產(chǎn)品。這里是通過(guò)配置導(dǎo)向器的生成器的子類(lèi)實(shí)例來(lái)實(shí)現(xiàn)的。

          4、 結(jié)構(gòu)

          wps_clip_image-372

          5、 參與者

          l Builder:為創(chuàng)建一個(gè)product對(duì)象的各個(gè)部件指定抽象接口。這些部件最終構(gòu)成了product,而對(duì)這些抽象接口的調(diào)用,則是裝配product的操作,調(diào)用的次數(shù),入?yún)⒌炔煌瑒t最終生成的product也不同。product本身的構(gòu)造過(guò)程可能會(huì)非常復(fù)雜。但是,這些復(fù)雜度對(duì)Director(導(dǎo)向者)是隱藏的。這些抽象的接口描述了產(chǎn)品的組成以及裝配方式。

          l ConcreteBuilder:實(shí)現(xiàn)Builder的接口以構(gòu)造和裝配產(chǎn)品的各個(gè)部件;定義并明確它所創(chuàng)建的表示;提供一個(gè)檢索產(chǎn)品的接口。這個(gè)類(lèi)實(shí)現(xiàn)了Builder的抽象接口,從而可以創(chuàng)建不同的表示,但是組成和裝配過(guò)程還是一樣的。

          l Director:構(gòu)造一個(gè)使用Builder抽象接口的對(duì)象。更對(duì)象根據(jù)Builder的接口來(lái)裝配并生產(chǎn)產(chǎn)品。

          l Product:表示被構(gòu)造的復(fù)雜的對(duì)象。ConcreteBuilder創(chuàng)建該產(chǎn)品的內(nèi)部表示,并定義它的裝配過(guò)程;包含定義組成部件的類(lèi),包括將這些部件裝配成最終產(chǎn)品的接口。

          6、 協(xié)作

          l 客戶創(chuàng)建Director對(duì)象,并用它想要的Builder對(duì)象進(jìn)行配置。

          l 一旦產(chǎn)品不僅被生成,導(dǎo)向器就會(huì)通知生成器。

          l 生成器處理導(dǎo)向器請(qǐng)求,并且將部件添加到該產(chǎn)品中。

          l 客戶從生成器中檢索產(chǎn)品。

          wps_clip_image-911

          7、 效果

          l 它使你可以改變一個(gè)產(chǎn)品的內(nèi)部表示。Builder提供給Director的抽象接口可以使生成器隱藏這個(gè)產(chǎn)品的表示和內(nèi)部結(jié)構(gòu)。它同時(shí)也隱藏了該產(chǎn)品時(shí)如何裝配的。因?yàn)楫a(chǎn)品時(shí)通過(guò)抽象接口構(gòu)造的,你改變?cè)摦a(chǎn)品的內(nèi)部表示時(shí),所要做的只是定義一個(gè)新的生成器。

          l 它將構(gòu)造代碼和表示代碼分開(kāi)。Builder模式通過(guò)封裝一個(gè)復(fù)雜對(duì)象的創(chuàng)建和表示方式提高了對(duì)象的模塊性。每個(gè)ConcreteBuilder包含了創(chuàng)建和裝配一個(gè)特定產(chǎn)品的所有代碼。

          l 它可以使你對(duì)構(gòu)造過(guò)程進(jìn)行更精細(xì)的控制。

          8、 實(shí)現(xiàn)

          l 通常一個(gè)抽象的Builder類(lèi)為導(dǎo)向者可能要求創(chuàng)建的每一個(gè)構(gòu)件定義一個(gè)操作。這些操作缺省什么也不做。一個(gè)ConcreteBuilder類(lèi)對(duì)它有興趣創(chuàng)建的構(gòu)建重定義這些操作。

          l 裝配和構(gòu)造接口:一般構(gòu)造請(qǐng)求的結(jié)果只是被添加到產(chǎn)品中,特殊情況下,需要返回給導(dǎo)向器。

          l 產(chǎn)品沒(méi)有抽象類(lèi):一般他們沒(méi)有公共的部分。如果有也可以設(shè)置一個(gè)抽象類(lèi)。

          l Builder中缺省的方法為空。

          9、 代碼示例

          class MazeBuilder {

          public:

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

              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,提供部件的具體構(gòu)造代碼

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

              builder.BuildMaze();

              builder.BuildRoom(1);

              builder.BuildRoom(2);

              builder.BuildDoor(1, 2);

              return builder.GetMaze();

          }//CreateMaze是導(dǎo)向器,調(diào)用生成器的抽象接口完成產(chǎn)品的構(gòu)造過(guò)程。

          //下面代碼描述產(chǎn)品的構(gòu)造過(guò)程

          Maze* maze;//最終的產(chǎn)品

          MazeGame game;//Director,導(dǎo)航者

          StandardMazeBuilder builder;//ConcreteBuilder,實(shí)際的構(gòu)造類(lèi)

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

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

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

          1.1 ABSTRACT FACTORY 抽象工廠

          1、 意圖

          提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴(lài)對(duì)象的接口,而無(wú)需指定他們具體的類(lèi)。

          2、 動(dòng)機(jī)

          “客戶僅與抽象定義的接口交互,而不使用特定的具體類(lèi)的接口。”

          這里的主要的思想是封裝對(duì)象的創(chuàng)建的過(guò)程。客戶端可以不需要知道具體要?jiǎng)?chuàng)建那些對(duì)象,而只需要知道創(chuàng)建某一系列的對(duì)象所用到的“工廠對(duì)象”即可。

          3、 適用性

          一個(gè)系統(tǒng)要獨(dú)立于它的產(chǎn)品的創(chuàng)建、組合和表示時(shí)。 

          一個(gè)系統(tǒng)要由多個(gè)產(chǎn)品系列中的一個(gè)來(lái)配置時(shí)。 

          當(dāng)你要強(qiáng)調(diào)一系列相關(guān)的產(chǎn)品對(duì)象的設(shè)計(jì)以便進(jìn)行聯(lián)合使用時(shí)。 

          當(dāng)你提供一個(gè)產(chǎn)品類(lèi)庫(kù),而只想顯示它們的接口而不是實(shí)現(xiàn)時(shí)。 

          4、 結(jié)構(gòu)

          wps_clip_image-278

          5、 參與者

          AbstractFactory:創(chuàng)建一系列對(duì)象的抽象類(lèi)。

          ConcreteFactory:實(shí)現(xiàn)具體創(chuàng)建產(chǎn)品對(duì)象的操作。

          AbstractProduct:為一類(lèi)產(chǎn)品對(duì)象聲明一個(gè)接口。

          ConcreteProduct:定義一個(gè)被相應(yīng)的具體工廠創(chuàng)建的對(duì)象;實(shí)現(xiàn)AbstractProduct接口。

          Client:僅使用AbstractFactory和AbstractProduct類(lèi)聲明的接口。

          6、 協(xié)作

          在運(yùn)行時(shí)刻,創(chuàng)建一個(gè)ConcreteFactory實(shí)例,它創(chuàng)建具有特定實(shí)現(xiàn)的對(duì)象。為創(chuàng)建不同的對(duì)象,客戶應(yīng)使用不同的具體工廠。

          AbstractFactory將具體對(duì)象的創(chuàng)建延遲到它的子類(lèi)ConcreteFactory中。

          7、 效果

          1) 它分離了具體的類(lèi):一個(gè)工廠封裝創(chuàng)建產(chǎn)品的責(zé)任和過(guò)程,它將客戶和類(lèi)的實(shí)現(xiàn)分離。客戶通過(guò)抽象接口操作實(shí)例。產(chǎn)品的類(lèi)名也在具體工廠實(shí)現(xiàn)中分離,他們不出現(xiàn)在客戶代碼中。

          2) 它使得易于交互產(chǎn)品系列。

          3) 它有利于產(chǎn)品的一致性。

          4) 難于支持新的種類(lèi)。

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

          1.1 設(shè)計(jì)模式怎樣解決設(shè)計(jì)問(wèn)題

          1.1.1 尋找合適的對(duì)象

          面向?qū)ο笤O(shè)計(jì)最困難的部分是將系統(tǒng)分解為對(duì)象的集合。

          設(shè)計(jì)的許多對(duì)象來(lái)源于現(xiàn)實(shí)世界的分析模型,這里和領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)有點(diǎn)關(guān)聯(lián)。分析所得到的類(lèi),很多事現(xiàn)實(shí)中并不存在的類(lèi)。這是抽象的結(jié)果。設(shè)計(jì)中的抽象對(duì)于產(chǎn)生靈活的設(shè)計(jì)至關(guān)重要。就像我設(shè)計(jì)的一個(gè)流程調(diào)度模型。

          1.1.2 決定對(duì)象的粒度

          記筆記可以讓我達(dá)到沉流的狀態(tài)。

          1.1.3 指定對(duì)象接口
          1.1.4 描述對(duì)象實(shí)現(xiàn)

          OMT表示法:

          1、 對(duì)象:最上面的黑體表示類(lèi)名,下面依次是操作,數(shù)據(jù)。

          wps_clip_image-219

          2、 實(shí)例化:虛線箭頭表示一個(gè)類(lèi)實(shí)例化另外一個(gè)對(duì)象。

          wps_clip_image-245

          3、 繼承:豎線和三角表示繼承關(guān)系。

          wps_clip_image-263

          4、 抽象類(lèi):類(lèi)名以黑體斜體表示,操作也用斜體表示。

          5、 引用

          wps_clip_image-293

          箭頭加黑點(diǎn)表示一個(gè)類(lèi)引用另外一個(gè)類(lèi)。

          重點(diǎn):

          1、 類(lèi)的繼承和接口繼承的比較

          對(duì)象的類(lèi)和對(duì)象的類(lèi)型的區(qū)別:

          對(duì)象的類(lèi)定義了對(duì)象是怎樣實(shí)現(xiàn)的,同時(shí)也定義了對(duì)象內(nèi)部狀態(tài)和操作的實(shí)現(xiàn)。對(duì)象的類(lèi)型只與它的接口有關(guān)。一個(gè)對(duì)象可以由多個(gè)類(lèi)型(支持多個(gè)接口),不同類(lèi)的對(duì)象可以有相同的類(lèi)型。

          類(lèi)和類(lèi)型緊密相連,類(lèi)定義了對(duì)象的操作,也定義了對(duì)象的類(lèi)型。

          類(lèi)的繼承和接口的繼承的差別:

          c++中接口繼承接近于公有繼承純抽象類(lèi)。純實(shí)現(xiàn)繼承或純類(lèi)繼承接近于私有繼承。

          2、 對(duì)接口編程,而不是對(duì)實(shí)現(xiàn)編程——面向?qū)ο笤O(shè)計(jì)的第一個(gè)原則

          1.1.5 運(yùn)用復(fù)用機(jī)制

          1、 繼承和組合的比較

          繼承是一種白箱復(fù)用,父類(lèi)的內(nèi)部細(xì)節(jié)對(duì)子類(lèi)可見(jiàn)。

          對(duì)象組合彼此不知道對(duì)方內(nèi)部細(xì)節(jié),成為黑箱復(fù)用。

          繼承的優(yōu)缺點(diǎn):

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

          2) 編譯時(shí)刻決定了,無(wú)法在運(yùn)行期間更改。

          3) 子類(lèi)要知道父類(lèi)的實(shí)現(xiàn)細(xì)節(jié),這樣就部分破壞了封裝性。子類(lèi)和父類(lèi)依賴(lài)過(guò)于緊密,父類(lèi)的某些變化必然導(dǎo)致子類(lèi)的變化。開(kāi)發(fā)過(guò)程中遇到過(guò)類(lèi)似的問(wèn)題。這種依賴(lài),限制了靈活性以及復(fù)用性。比如,服務(wù)體系中經(jīng)常出現(xiàn)這樣的問(wèn)題,導(dǎo)致代碼拷貝。

          組合(通過(guò)獲得對(duì)象的引用而在運(yùn)行時(shí)刻動(dòng)態(tài)的定義)的優(yōu)缺點(diǎn):

          1) 對(duì)象間通過(guò)接口彼此交互。

          2) 對(duì)象只能通過(guò)接口訪問(wèn),不要也不能知道對(duì)方細(xì)節(jié),這樣不會(huì)破壞封裝性。

          3) 運(yùn)行時(shí)刻可以使用另外一個(gè)對(duì)象替換這個(gè)對(duì)象,提高了靈活性。

          4) 對(duì)象的實(shí)現(xiàn)基于接口編寫(xiě),所以實(shí)現(xiàn)上存在較少的依賴(lài)關(guān)系。

          5) 優(yōu)先使用組合有助于保持每個(gè)類(lèi)被封裝,并被集中在單個(gè)任務(wù)上,提高整體內(nèi)聚性。類(lèi)和類(lèi)的層次都維持一個(gè)較小的規(guī)模,

          6) 基于對(duì)象組合的設(shè)計(jì)會(huì)有更多的對(duì)象(而又較少的類(lèi)),且系統(tǒng)的行為依賴(lài)于對(duì)象間的關(guān)系而不是定義在某個(gè)類(lèi)的內(nèi)部。

          理想的情況下,應(yīng)該通過(guò)組合原有構(gòu)件實(shí)現(xiàn)新的功能,而不是創(chuàng)建新的構(gòu)件。

          面向?qū)ο笤O(shè)計(jì)的第二個(gè)原則:優(yōu)先使用對(duì)象組合,而不是類(lèi)繼承。

          2、 委托

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

          委托的主要優(yōu)點(diǎn)在于它便于在運(yùn)行時(shí)刻組合對(duì)象操作,以及更改操作的組合方式。它是軟件更加的靈活。

          和其他的技術(shù)方案相同,它也存在不足之處:增加了軟件的復(fù)雜度——?jiǎng)討B(tài)的,高度參數(shù)化的軟件比靜態(tài)的軟件更難于理解。

          3、 繼承和參數(shù)化類(lèi)型的比較

          1.1.6 關(guān)聯(lián)運(yùn)行時(shí)刻的結(jié)構(gòu)和編譯時(shí)刻的結(jié)構(gòu)
          1.1.7 設(shè)計(jì)應(yīng)支持變化

          設(shè)計(jì)應(yīng)該支持變化——所說(shuō)的是,一個(gè)設(shè)計(jì)方案,對(duì)變化要有一定的適應(yīng)性,即封裝變化。

          變化是導(dǎo)致重新設(shè)計(jì)的原因。設(shè)計(jì)要對(duì)一定范圍內(nèi)的變化友好。

          4、 

          對(duì)于程序的分層設(shè)計(jì),對(duì)于處于同一分層的模塊,對(duì)外應(yīng)保持一定的抽象,并且,使用同種類(lèi)型的通信協(xié)議。

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

          1.1 變量存儲(chǔ)域

          1.1.1 一個(gè)示例

          pang123hui首先提供了一個(gè)網(wǎng)上流傳的學(xué)習(xí)代碼示例:

          int a = 0; //全局區(qū) 

          void main() 

          {

          int b; //棧 

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

          char *p1,*p2; //棧 

          char *p3 = "123456"; //123456在常量區(qū),p3在棧上 

          static int c =0; //全局區(qū) 

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

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

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

          }

          這個(gè)代碼示例中出現(xiàn)了“全局區(qū)”,“棧”,“文字常量區(qū)”,“堆”等詞語(yǔ)。為了統(tǒng)一,我們使用《C專(zhuān)家編程》中的說(shuō)法:堆棧段,BSS段,數(shù)據(jù)段,文本段。

          各個(gè)段的作用如下:

          1、 文本段:包含程序的指令,它在程序的執(zhí)行過(guò)程中一般不會(huì)改變。

          2、 數(shù)據(jù)段:包含了經(jīng)過(guò)初始化的全局變量和靜態(tài)變量,以及他們的值。

          3、 BSS段:包含未經(jīng)初始化的全局變量和靜態(tài)變量。

          4、 堆棧段:包含了函數(shù)內(nèi)部聲明的局部變量。

          當(dāng)然,上面段的作用不僅于此,具體的作用會(huì)在下面的知識(shí)點(diǎn)中介紹。

          1.1.2 通過(guò)代碼測(cè)試變量的存儲(chǔ)位置

          Linux下可以通過(guò)系統(tǒng)命令“size”查看可以執(zhí)行程序各個(gè)段的大小。但是,可執(zhí)行程序中的段結(jié)構(gòu)和運(yùn)行中程序在內(nèi)存中的段結(jié)構(gòu)并不完全相同,但是有一定的映射關(guān)系。具體如下圖所示(圖片信息來(lái)自《C專(zhuān)家編程》):

          wps_clip_image-696

          下面通過(guò)代碼示例和“size”來(lái)研究變量的存儲(chǔ)區(qū)域。

          test.c

          int main()

          {

          return 1;

          }

          編譯,并且查看可執(zhí)行程序各個(gè)段的大小:

          wps_clip_image-779

          更改test.c:

          int g_data;

          int main()

          {

          return 1;

          }

          編譯,并且查看可執(zhí)行程序各個(gè)段的大小:

          wps_clip_image-849

          可以發(fā)現(xiàn),文本段,數(shù)據(jù)段都沒(méi)有發(fā)送變化,而B(niǎo)SS段增加了4個(gè)字節(jié)。

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

          繼續(xù):

          int g_data = 1;

          int main()

          {

          return 1;

          }

          編譯:

          wps_clip_image-958

          可以發(fā)現(xiàn),BSS段和文本段相同,而數(shù)據(jù)段增加了4個(gè)字節(jié)。

          結(jié)論2:經(jīng)過(guò)初始化的全局變量保存在數(shù)據(jù)段中

          繼續(xù):

          int main()

          {

          static int g_data;

          return 1;

          }

          編譯:

          wps_clip_image-1066

          可以發(fā)現(xiàn),文本段,數(shù)據(jù)段都沒(méi)有發(fā)送變化,而B(niǎo)SS段增加了4個(gè)字節(jié)。

          結(jié)論3:未初始化的靜態(tài)變量保存在BSS段中

          繼續(xù):

          int main()

          {

          static int g_data = 1;

          return 1;

          }

          編譯:

          wps_clip_image-1183

          可以發(fā)現(xiàn),BSS段和文本段相同,而數(shù)據(jù)段增加了4個(gè)字節(jié)。

          結(jié)論4:經(jīng)過(guò)初始化的靜態(tài)變量保存在數(shù)據(jù)段中

          繼續(xù):

          int main()

          {

          int i_data = 1;

          return 1;

          }

          編譯:

          wps_clip_image-1288

          可以發(fā)現(xiàn),BSS段和和數(shù)據(jù)段相同,而文本段增加了16個(gè)字節(jié)。局部變量會(huì)在執(zhí)行的時(shí)候在堆棧段中生成,函數(shù)執(zhí)行完畢后釋放。

          結(jié)論5:函數(shù)內(nèi)部聲明的局部變量保存在堆棧段中

          繼續(xù):

          const int g_data = 1;

          int main()

          {

          return 1;

          }

          編譯:

          wps_clip_image-1430

          把全局變量定義為“const”后,也許你會(huì)感到奇怪,怎么BSS段和數(shù)據(jù)段都沒(méi)有發(fā)生變化,而文本段卻增加了4個(gè)字節(jié)。

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

          那么,const的局部變量?

          繼續(xù):

          int main()

          {

          const int i_data = 1;

          return 1;

          }

          編譯:

          wps_clip_image-1587

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

          繼續(xù):

          char *pstr = "";

          int main()

          {

          return 1;

          }

          編譯:

          wps_clip_image-1666

          在做一下更改:

          char *pstr = "123456789";

          int main()

          {

          return 1;

          }

          編譯:

          wps_clip_image-1733

          可以發(fā)現(xiàn),前后數(shù)據(jù)段和BSS段大小均未發(fā)生變化,而文本段增加了9個(gè)字節(jié)。

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

          1.1.3 結(jié)論

          1、 經(jīng)過(guò)初始化的全局變量和靜態(tài)變量保存在數(shù)據(jù)段中。

          2、 未經(jīng)初始化的全局變量和靜態(tài)變量保存在BSS段。

          3、 函數(shù)內(nèi)部聲明的局部變量保存在堆棧段中。

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

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

          1.1.4 擴(kuò)展閱讀

          《C專(zhuān)家編程》第6章——詳細(xì)介紹各個(gè)段的作用。

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


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

          Copyright © 常高偉

          主站蜘蛛池模板: 西吉县| 青铜峡市| 宁德市| 牟定县| 乌鲁木齐市| 大庆市| 新营市| 永新县| 中宁县| 山阴县| 平度市| 赤水市| 鄯善县| 土默特左旗| 鹿邑县| 嘉黎县| 渭南市| 都江堰市| 印江| 荣昌县| 兴国县| 安徽省| 泾源县| 赤水市| 东山县| 麦盖提县| 柳州市| 伊金霍洛旗| 宜兰市| 宣恩县| 高雄县| 宜黄县| 仁寿县| 乌拉特后旗| 彭阳县| 肃北| 无锡市| 临沂市| 赤壁市| 砚山县| 称多县|