• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            積木

            No sub title

              C++博客 :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
              140 Posts :: 1 Stories :: 11 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(1)

            我參與的團(tuán)隊(duì)

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            轉(zhuǎn)載自:http://patmusing.blog.163.com/blog/static/13583496020101501825958/


            Aka. Token

            在不破壞封裝性的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài),并在該對(duì)象之外保存其狀態(tài)這樣以后就可以將該對(duì)象恢復(fù)到原先保存的狀態(tài)。

            “Without violating encapsulation, capture and externalize an object’s internal state so that the object can be restored to this state later.” – GoF

            動(dòng)機(jī)

            有時(shí)候需要記錄一個(gè)對(duì)象的內(nèi)部狀態(tài)。比如要實(shí)現(xiàn)checkpoint或者undo這樣的機(jī)制,可以讓使用者從臨時(shí)性的操作跳出來(lái)或者需要修復(fù)錯(cuò)誤的時(shí)候,你必須將狀態(tài)信息保存在某個(gè)地方,以便在進(jìn)行某些操作后,將對(duì)象恢復(fù)到原來(lái)的狀態(tài)。但通常情況下,對(duì)象封裝了狀態(tài)(即私有成員變量),因此其他的對(duì)象無(wú)法訪問(wèn)這些狀態(tài),而且也不可能將這些狀態(tài)保存在對(duì)象之外。如果將這些狀態(tài)設(shè)置成公有的,又會(huì)違反面向?qū)ο蠓庋b性的原則,同時(shí)也會(huì)削弱應(yīng)用的可靠性和可擴(kuò)展性。

            在軟件構(gòu)建過(guò)程中, 某些對(duì)象的狀態(tài)在轉(zhuǎn)換過(guò)程中,可能由于某種需要,要求程序能夠回溯到對(duì)象之前處于某個(gè)時(shí)刻的狀態(tài)。如果使用一些共有接口來(lái)讓其他對(duì)象得到對(duì)象的狀態(tài),便會(huì)暴露對(duì)象的細(xì)節(jié)實(shí)現(xiàn)。Memento設(shè)計(jì)模式就可以實(shí)現(xiàn)對(duì)象狀態(tài)的良好保存與恢復(fù),但同時(shí)又不會(huì)因此而破壞對(duì)象本身的封裝性。

            UML類(lèi)圖:

            21. C++實(shí)現(xiàn)Behavioral - Memento模式 - 玄機(jī)逸士 - 玄機(jī)逸士博客

            角色

            - Memento

            1. 保存Originator對(duì)象的內(nèi)部狀態(tài)。

            2. Originator外,其他對(duì)象均不能訪問(wèn)Memento對(duì)象。

            - Originator

            1. 創(chuàng)建一個(gè)包含其當(dāng)前內(nèi)部狀態(tài)快照的Memento對(duì)象。

            2. 使用Memento對(duì)象來(lái)恢復(fù)其內(nèi)部狀態(tài)。

            - Caretaker

            1. Memento對(duì)象的容器。在C++中一般用stack來(lái)實(shí)現(xiàn)。

            2. 從不對(duì)Memento對(duì)象的內(nèi)容進(jìn)行檢查或操作。

            示例代碼:

            // Memento.h

            #include <iostream>

            #include <stack>

            using namespace std;

            // CMemento類(lèi),用來(lái)保存CRectangle的狀態(tài)

            class CMemento

            {

            private: // 所有的成員變量和成員函數(shù)都是私有的

            int topx; // 因此除友元類(lèi)CRectangle外,其他對(duì)象都無(wú)法訪問(wèn)

            int topy;

            int width;

            int height;

            private:

            CMemento()

            {

            }

            //private: // 1. 如果編寫(xiě)了顯式拷貝構(gòu)造函數(shù),那么,它必須是公有的,

            // CMemento(const CMemento& memo) // 否則CMementoStack將無(wú)法調(diào)用該拷貝構(gòu)造函數(shù)。

            // { // 2. 如果沒(méi)有顯式的拷貝構(gòu)造函數(shù),那么缺省的拷貝構(gòu)造函數(shù)總是公有的。

            // topx = memo.topx; // 3. Memento模式中,如果僅考慮保存一次狀態(tài),則

            // topy = memo.topy; // CMementoStack是不必要的,那么拷貝構(gòu)造函數(shù),可以

            // width = memo.width; // 顯式地聲明為private的,盡管在CRectanglecreate_memento

            // height = memo.height; // 成員函數(shù)中也會(huì)調(diào)用CMemento的拷貝構(gòu)造函數(shù),但CRectangle

            // } // CMemento的友元類(lèi),因此不存在這方面的限制。

            private:

            void set_state(int topx, int topy, int width, int height) // 保存CRectangle的狀態(tài)

            {

            this->topx = topx;

            this->topy = topy;

            this->width = width;

            this->height = height;

            }

            friend class CRectangle; // 友元類(lèi)CRectangle,可以訪問(wèn)CMemento中的所有內(nèi)容

            };

            // CRectangle類(lèi)。一個(gè)矩形,需要保存狀態(tài)改變的類(lèi)

            class CRectangle

            {

            private:

            int topx; // 矩形左上角的x坐標(biāo)

            int topy; // 矩形左上角的y坐標(biāo)

            int width; // 矩形的寬

            int height; // 矩形的高

            public:

            CRectangle(int topx, int topy, int width, int height):topx(topx), topy(topy), width(width), height(height)

            {

            }

            // 模擬移動(dòng)矩形的位置到指定的點(diǎn),即改變了矩形的狀態(tài)

            void move_to(int topx, int topy)

            {

            this->topx = topx;

            this->topy = topy;

            }

            // 模擬改變矩形的長(zhǎng)和寬,即改變了矩形的狀態(tài)

            void change_width_height(int width, int height)

            {

            this->width = width;

            this->height = height;

            }

            // 將矩形恢復(fù)到memo中所保存的狀態(tài)

            void set_memento(CMemento memo)

            {

            this->topx = memo.topx;

            this->topy = memo.topy;

            this->width = memo.width;

            this->height = memo.height;

            }

            // 將矩形的狀態(tài)保存到一個(gè)CMemento對(duì)象

            CMemento create_memento()

            {

            CMemento cm;

            cm.set_state(this->topx, this->topy, this->width, this->height);

            return cm;

            }

            // 輸出矩形的狀態(tài)信息

            void print_info()

            {

            cout << "Top left point's x coordinate: " << topx << endl;

            cout << "Top left point's y coordinate: " << topy << endl;

            cout << "The width is: " << width << endl;

            cout << "The height is: " << height << endl;

            }

            };

            // CMemento對(duì)象的容器,可以用來(lái)保存多個(gè)CMemento對(duì)象,通常用stack來(lái)實(shí)現(xiàn)

            class CMementoStack

            {

            private:

            stack<CMemento> stk;

            public:

            void add_memento(CMemento memo)

            {

            stk.push(memo); //CMemento對(duì)象壓入棧中

            }

            CMemento get_memento()

            {

            CMemento cm = stk.top(); // 取得CMemento對(duì)象。這個(gè)過(guò)程會(huì)用到CMemento類(lèi)的拷貝構(gòu)造函數(shù),

            // 由于CMemento對(duì)象中的成員變量均是普通類(lèi)型(非指針、非類(lèi)對(duì)象),

            // 因此使用默認(rèn)的拷貝構(gòu)造函數(shù)即可

            stk.pop(); // 刪除已經(jīng)取得的CMemento對(duì)象

            return cm;

            }

            };

            // Memento.cpp

            #include "Memento.h"

            int main(int argc, char **argv)

            {

            CRectangle cr(10, 10, 100, 100);

            CMementoStack cs;

            cout << "Initial states: " << endl;

            cr.print_info();

            CMemento cm0 = cr.create_memento(); // 將狀態(tài)保存到CMemento對(duì)象

            cs.add_memento(cm0); // CMemento對(duì)象壓棧

            // 第一次改變狀態(tài)

            cr.change_width_height(200, 200); // 改變矩形的高度和寬度

            cr.move_to(20, 20); // 改變矩形的位置

            cout << "\nAfter 1st states changed: " << endl;

            cr.print_info();

            CMemento cm1 = cr.create_memento(); // 將狀態(tài)保存到CMemento對(duì)象

            cs.add_memento(cm1); // CMemento對(duì)象壓棧

            // 第二次改變狀態(tài)

            cr.change_width_height(300, 300); // 改變矩形的高度和寬度

            cr.move_to(30, 30); // 改變矩形的位置

            cout << "\nAfter 2nd states changed: " << endl;

            cr.print_info();

            // ... 這里不再壓棧

            // 恢復(fù)到第一次狀態(tài)的改變

            cr.set_memento(cs.get_memento());

            cout << "\nStates restored to 1st change: " << endl;

            cr.print_info();

            // 恢復(fù)到初始狀態(tài)

            cr.set_memento(cs.get_memento());

            cout << "\nStates restored to initial: " << endl;

            cr.print_info();

            }

            運(yùn)行結(jié)果:

            Initial states:

            Top left point's x coordinate: 10

            Top left point's y coordinate: 10

            The width is: 100

            The height is: 100

            After 1st states changed:

            Top left point's x coordinate: 20

            Top left point's y coordinate: 20

            The width is: 200

            The height is: 200

            After 2nd states changed:

            Top left point's x coordinate: 30

            Top left point's y coordinate: 30

            The width is: 300

            The height is: 300

            States restored to 1st change:

            Top left point's x coordinate: 20

            Top left point's y coordinate: 20

            The width is: 200

            The height is: 200

            States restored to initial:

            Top left point's x coordinate: 10

            Top left point's y coordinate: 10

            The width is: 100

            The height is: 100

            結(jié)果符合預(yù)期。

            補(bǔ)充說(shuō)明:

            1. 未設(shè)置其成員變量為public的前提下,在對(duì)象的外部保存一個(gè)其狀態(tài),頗需技巧,而且用不同語(yǔ)言來(lái)實(shí)現(xiàn)的時(shí)候也有所不同。

            a. 對(duì)于C++,通常使用友元類(lèi)來(lái)實(shí)現(xiàn)。

            b. 對(duì)于C#,使用internal關(guān)鍵字。

            c. 對(duì)于Java,使用package protected訪問(wèn)控制。

            與其處于相同包中的子類(lèi),和處于相同包中的其它類(lèi)均可以訪問(wèn)pakcage protected的對(duì)象或變量。

            Java中的訪問(wèn)權(quán)限有public,private,protected和默認(rèn)的包訪問(wèn)權(quán)限,如果類(lèi)中的屬性方法沒(méi)有顯示的指明訪問(wèn)權(quán)

            限,則具有包訪問(wèn)權(quán)限,很多人也稱(chēng)它為friendly訪問(wèn)權(quán)限,也有人稱(chēng)為packeged權(quán)限,而packagedfriendly

            這兩個(gè)關(guān)鍵字在實(shí)際中都是不存在的。在Java中,訪問(wèn)權(quán)限修飾符權(quán)限從高到低是public,protected,package

            protectedprivate。

            d. C++, C#Java均可使用內(nèi)部類(lèi)的方式來(lái)實(shí)現(xiàn)類(lèi)似的功能,不過(guò)對(duì)于“將狀態(tài)存儲(chǔ)于對(duì)象之外”而言,稍嫌勉強(qiáng)。

            2. 關(guān)于拷貝構(gòu)造函數(shù),請(qǐng)看:http://patmusing.blog.163.com/blog/static/1358349602009113061024796/

            3. 關(guān)于友元類(lèi),請(qǐng)看:http://patmusing.blog.163.com/blog/static/1358349602010182331153/



            posted on 2013-03-08 14:51 Jacc.Kim 閱讀(208) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): 設(shè)計(jì)模式
            日本欧美久久久久免费播放网| 久久久久久噜噜精品免费直播 | 69SEX久久精品国产麻豆| 伊人久久大香线焦AV综合影院 | 伊人精品久久久久7777| 亚洲精品无码久久久久| 国产精品美女久久久免费| 精品国产乱码久久久久软件| 久久大香香蕉国产| 开心久久婷婷综合中文字幕| 国产美女久久精品香蕉69| 青青青青久久精品国产h久久精品五福影院1421 | 久久亚洲私人国产精品vA| 久久国产精品波多野结衣AV| 久久久av波多野一区二区| 亚洲乱码日产精品a级毛片久久 | 久久精品中文字幕大胸| 国产精品久久永久免费| 久久精品国产久精国产果冻传媒 | 亚洲精品无码专区久久久 | 久久国产精品77777| 久久成人小视频| 国产精品伦理久久久久久| 久久精品亚洲精品国产色婷| 97精品伊人久久久大香线蕉| 久久综合亚洲色HEZYO国产| 99久久人人爽亚洲精品美女| 久久久久亚洲精品无码蜜桃| 亚洲人成网亚洲欧洲无码久久 | 精品久久人人爽天天玩人人妻| www性久久久com| 久久婷婷五月综合色高清 | 精品久久久久久无码国产| 久久综合九色综合久99| 久久亚洲精品中文字幕三区| 精品熟女少妇av免费久久| 精品无码久久久久久尤物| 国产精品久久久久jk制服| 国产精品一区二区久久精品| 国产精品久久久久久| 亚洲成人精品久久|