• <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>

            huaxiazhihuo

             

            C++沉思錄課堂練習(xí)另解--消息發(fā)送(優(yōu)化版)

                      緣起,看到一篇文章(懶得超鏈接),重新研究《C++沉思錄》的那一個課堂練習(xí),綜合利用好幾種設(shè)計模式,并且很好地遵守結(jié)合的面向?qū)ο蟮脑瓌t,嗯,不管怎么樣,還是表揚(yáng)這位同學(xué)的面向?qū)ο笈c設(shè)計模式的功力,確實不容易。只是,在下從模式堆里爬出來之后,已經(jīng)對模式大倒胃口,看到這么小的練習(xí),居然要用上這么多模式,一時技癢,有必要這樣嗎?對我來說,代碼中每引入一種模式,就表示要添加各種接口、虛函數(shù),然后,免不了就要用到繼承,這些,我非常深痛惡疾,因為,這都意味著間接層越來越厚了,偏離了問題的本質(zhì)。
                      先看看沉思錄對于這道題的描述,嗯,這個,還是請各位自己去看看書是怎么寫的,作者提供了兩種方案,佩服作者和譯者的文筆,兩種方案解釋得相當(dāng)細(xì)膩。下面,嘗試另一種解決方式。先秀一下代碼的運(yùn)行效果。
                      對于這個課堂練習(xí),其中,給圖片加邊框,最適合于用裝飾模式來解決。但是,兩幅圖片的橫接、豎接,怕是就不那么容易了。但是,首先,要對問題重新描述一下,現(xiàn)實中,一張圖片,可以給予添加一層又一層的片框,也可以和其他的圖片組合在一塊,或橫,或豎,……,但是,圖片,始終只有一張,對它處理之后,它就一直是那個樣子了,不可能同時看到它的兩個樣子。如果,拿這張圖片去進(jìn)行復(fù)制,那又自是另當(dāng)別論,但那已經(jīng)是另外一張新圖片了。
                      以下的設(shè)計用上了消息,如果有現(xiàn)成消息框架給予支持,實現(xiàn)起來就會很簡單。但是,即使沒有消息框架的支持,利用消息發(fā)送來解決這個問題,也是相當(dāng)小兒科的事情。為了突出重點,忽略了各種異常處理,沒有優(yōu)化,也不管什么編程風(fēng)格,純粹直奔主題。解決這個例子的最重要一點,就在于打印圖片時,要一行一行地從頂?shù)降醉槾未蛴∠聛怼R虼耍榷x這個圖片可以發(fā)送的消息,它必須處理兩條消息,圖片的高度(即行數(shù)),和圖片每一行的數(shù)據(jù)。即如下所示
            enum {PM_HEIGHT, PM_ROW};

            struct PictureMsg
            {
                typedef 
            int (*ProcPictureMsg)(void* pThis, int nMessage, void* param1, void* param2);
            public:
                
            void* pThis;
                ProcPictureMsg proc;

                
            int GetHeight()
                
            {
                    
            return (*proc)(pThis, PM_HEIGHT, NULL, NULL);
                }


                
            int GetRow(int nRow, string& sRow)
                
            {
                    
            return (*proc)(pThis, PM_ROW, (void*)nRow, (void*)&sRow);
                }

            }
            ;
            ostream
            & operator << (ostream& out, PictureMsg& msg)
            {
                
            int nHeight = msg.GetHeight();
                
            string sRow;
                
            for (int nRow = 0; nRow<nHeight; nRow++)
                
            {
                    sRow.clear();
                    msg.GetRow(nRow, sRow);
                    
            out << sRow;
                    
            out << endl;
                }

                
            return out;
            }

                      其中的回調(diào)函數(shù)用以發(fā)送消息,本來回調(diào)函數(shù)搞成成員函數(shù)會更加好,但由于c++的成員函數(shù)是一個大坑,而我又不想引入function或者其他delegate等龐然大物。為了讓客戶更加方便地發(fā)送消息,特意編寫了兩個輔助函數(shù)。
                      但是,要發(fā)送消息給對象時,首先要求這個對象必須已經(jīng)活著了,也即是要創(chuàng)建一個能接收消息的對象。由于沒有消息框架的支持,同時,也為了使用上的方便,我只好編寫一個具體的類繼承于圖片消息結(jié)構(gòu),并提供了初步的消息處理,嗯,用到了繼承,很難受。
                      好了,接下來就可以全心全意地對消息進(jìn)行特別地處理了。要求,對圖片的各種裝飾操作,不能影響到圖片原有的功能,也不要求改變用戶的代碼。或者說,圖片本身并不知道自己已經(jīng)被外界做了各種各樣的處理,它還是按照原來的樣子處理各種消息。下面,只是實現(xiàn)了兩種裝飾操作,加邊框與橫接,至于豎接,實在很容易實現(xiàn)的。此外,由于在實現(xiàn)裝飾操作時,需要用到圖片的寬度,因此,圖片消息又添加了一條新的消息,用以處理圖片的寬度。
            由于是玩具代碼,在下也沒有做太大的優(yōu)化,有幾行代碼顯得特別難看,特別是橫接的裝飾方法,強(qiáng)制指定了左邊的圖片為操作后的結(jié)果,還有各個裝飾類的析構(gòu)函數(shù),可以撤消對圖片的裝飾,以及添加新的消息,以返回圖片的拷貝,或返回當(dāng)前正在進(jìn)行的裝飾操作,或者裝飾類的動態(tài)創(chuàng)建等等。總之,可優(yōu)化升級的方法多種多樣,而且都不會影響代碼的結(jié)構(gòu)。以下,是一陀代碼,從第一版上稍加優(yōu)化的,不讀也罷。

            enum { PM_WIDTH, PM_HEIGHT, PM_ROW};

            struct PictureMsg
            {
                typedef 
            int (*ProcPictureMsg)(void* pThis, int nMessage, void* param1, void* param2);
            public:
                
            void* pThis;
                ProcPictureMsg proc;

                
            int GetWidth()
                
            {
                    
            return (*proc)(pThis, PM_WIDTH, NULL, NULL);
                }


                
            int GetHeight()
                
            {
                    
            return (*proc)(pThis, PM_HEIGHT, NULL, NULL);
                }


                
            int GetRow(int nRow, string& sRow)
                
            {
                    
            return (*proc)(pThis, PM_ROW, (void*)nRow, (void*)&sRow);
                }

            }
            ;

            ostream
            & operator << (ostream& out, PictureMsg& msg)
            {
                
            int nHeight = msg.GetHeight();
                
            string sRow;
                
            for (int nRow = 0; nRow<nHeight; nRow++)
                
            {
                    sRow.clear();
                    msg.GetRow(nRow, sRow);
                    
            out << sRow;
                    
            out << endl;
                }

                
            return out;
            }


            class CPicture : public PictureMsg
            {
            public:
                CPicture(
            const char* pDatas[], int nCount)
                
            {
                    m_pDatas 
            = pDatas;
                    m_nCount 
            = nCount;
                    m_nWidth 
            = 0;
                    
            for (int i=0; i<m_nCount; i++)
                    
            {
                        
            int nLen = strlen(m_pDatas[i]);
                        
            if (m_nWidth < nLen)
                            m_nWidth 
            = nLen;
                    }

                    pThis 
            = this;
                    proc 
            = HandleMsg;
                }


            private:
                
            const char** m_pDatas;
                
            int m_nCount;
                
            int m_nWidth;

                
            static int HandleMsg(void* pThis, int nMessage, void* param1, void* param2);
            }
            ;

            int CPicture::HandleMsg(void* pThis, int nMessage, void* param1, void* param2)
            {
                CPicture
            * pSelf = (CPicture*)pThis;
                
            switch (nMessage)
                
            {
                
            case PM_WIDTH:
                    
            return pSelf->m_nWidth;

                
            case  PM_HEIGHT:
                    
            return pSelf->m_nCount;
                    
            break;

                
            case PM_ROW:
                    
            int nRow = (int)param1;
                    
            string& sRow = *(string*)param2;
                    
            if (nRow >= pSelf->m_nCount)
                        
            break;
                    
            int i=0
                    
            for (; pSelf->m_pDatas[nRow][i] != 0; i++)
                        sRow.push_back(pSelf
            ->m_pDatas[nRow][i]);
                    
            for (; i<pSelf->m_nWidth; i++)
                        sRow.push_back(
            ' ');                
                }

                
            return 0;
            }



            class CFrameDecorater
            {
            public:
                CFrameDecorater(PictureMsg
            & imp)
                
            {
                    m_PrevImp 
            = imp;
                    imp.pThis 
            = this;
                    imp.proc 
            = HandleMsg;
                }


            private:
                PictureMsg m_PrevImp;
                
            static int HandleMsg(void* pThis, int nMessage, void* param1, void* param2);
            }
            ;

            int CFrameDecorater::HandleMsg(void* pThis, int nMessage, void* param1, void* param2)
            {
                CFrameDecorater
            * pSelf = (CFrameDecorater*)pThis;
                PictureMsg
            & prevImp = pSelf->m_PrevImp;
                
            switch (nMessage)
                
            {
                
            case PM_WIDTH:
                    
            return prevImp.GetWidth()+2;

                
            case  PM_HEIGHT:
                    
            return prevImp.GetHeight()+2;

                
            case PM_ROW:
                    
            int nRow = (int)param1;
                    
            string& sRow = *(string*)param2;
                    
            bool bMyRow = nRow == 0 || nRow>prevImp.GetHeight();
                    
            if (nRow >= prevImp.GetWidth()+2)
                        
            break;
                    
            if (nRow == 0 || nRow>prevImp.GetHeight())
                    
            {
                        sRow.push_back(
            '+');
                        
            for (int i=0; i<prevImp.GetWidth(); i++)
                            sRow.push_back(
            '-');
                        sRow.push_back(
            '+');
                    }

                    
            else
                    
            {
                        sRow.push_back(
            '|');
                        prevImp.GetRow(nRow
            -1, sRow);
                        sRow.push_back(
            '|');
                    }

                }

                
            return 0;
            }



            class CHorseDecorater
            {
            public:
                CHorseDecorater(PictureMsg
            & impLeft, PictureMsg& impRight)
                
            {
                    m_Left 
            = impLeft;
                    m_Right 
            = impRight;
                    impLeft.pThis 
            = this;
                    impLeft.proc 
            = HandleMsg;
                }


            private:
                PictureMsg m_Left;
                PictureMsg m_Right;

                
            static int HandleMsg(void* pThis, int nMessage, void* param1, void* param2);
                
            static void PrintRow(PictureMsg& pict, int nRow, string& sRow)
                
            {
                    
            if (nRow < pict.GetHeight())
                        pict.GetRow(nRow, sRow);
                    
            else
                    
            {
                        
            for (int i=0; i<pict.GetWidth(); i++)
                            sRow.push_back(
            ' ');
                    }

                }

            }
            ;

            int CHorseDecorater::HandleMsg(void* pThis, int nMessage, void* param1, void* param2)
            {
                CHorseDecorater
            * pSelf = (CHorseDecorater*)pThis;
                PictureMsg
            & pictLeft = pSelf->m_Left;
                PictureMsg
            & pictRight = pSelf->m_Right;
                
            switch (nMessage)
                
            {
                
            case PM_WIDTH:
                    
            return pictLeft.GetWidth()+pictRight.GetWidth();;

                
            case  PM_HEIGHT:
                    
            return max(pictLeft.GetHeight(), pictRight.GetHeight());

                
            case PM_ROW:
                    
            int nRow = (int)param1;
                    
            string& sRow = *(string*)param2;
                    PrintRow(pictLeft, nRow, sRow);
                    PrintRow(pictRight, nRow, sRow);
                }

                
            return 0;
            }


            int main()
            {
                
            const char* init1[] = {"Paris""in the""Spring""HaHa"};
                CPicture pict1(init1, 
            3);
                
            //cout << pict1;
                CFrameDecorater framer1(pict1);
                
            //cout << pict1;
                CFrameDecorater framer2(pict1);
                
            //cout << pict1;
                CPicture pict2(init1, 4);
                CHorseDecorater hors(pict1, pict2);
                
            //cout << pict1;
                CFrameDecorater framerHorse(pict1);
                
            //cout << pict1;
                CHorseDecorater hors2( pict2,  pict1);
                
            //cout << pict2;
                CFrameDecorater framer3(pict2);
                CHorseDecorater hors3( pict1,  pict2);
                cout 
            << pict1;
                
            return 0;
            }



            posted on 2012-06-12 23:57 華夏之火 閱讀(2085) 評論(0)  編輯 收藏 引用 所屬分類: 玩具代碼

            導(dǎo)航

            統(tǒng)計

            常用鏈接

            留言簿(6)

            隨筆分類

            隨筆檔案

            搜索

            積分與排名

            最新評論

            閱讀排行榜

            評論排行榜

            国产精品美女久久久久网| 久久久久久久综合日本| 亚洲国产天堂久久综合网站| 国产精品青草久久久久福利99| 亚洲精品国产第一综合99久久| 一本一本久久a久久综合精品蜜桃| 久久久婷婷五月亚洲97号色| 国产精品九九久久免费视频 | 欧美伊人久久大香线蕉综合69 | 久久久久久国产精品无码超碰| 久久亚洲国产午夜精品理论片| 性做久久久久久免费观看| 久久精品一本到99热免费| 久久五月精品中文字幕| 久久久久人妻精品一区二区三区 | 66精品综合久久久久久久| 久久久久人妻一区二区三区| 久久99热精品| 久久婷婷五月综合97色| 久久亚洲电影| 久久国产一片免费观看| 国产三级久久久精品麻豆三级| 最新久久免费视频| 亚洲国产成人精品91久久久| 国产精品久久久久乳精品爆| 99久久久国产精品免费无卡顿| 久久夜色精品国产亚洲| 久久人人爽人爽人人爽av| 亚洲国产二区三区久久| 99re久久精品国产首页2020| 国内高清久久久久久| 欧美一区二区久久精品| 一级a性色生活片久久无| 无码国内精品久久人妻麻豆按摩| 久久精品99无色码中文字幕| 国产精品永久久久久久久久久| 久久国产精品99久久久久久老狼| 精品久久久无码人妻中文字幕豆芽| 99久久精品免费看国产一区二区三区 | 久久人人爽人人爽人人片AV不 | 无码AV中文字幕久久专区|