• <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++沉思錄課堂練習另解--消息發送(優化版)

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

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

            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 華夏之火 閱讀(2086) 評論(0)  編輯 收藏 引用 所屬分類: 玩具代碼

            導航

            統計

            常用鏈接

            留言簿(6)

            隨筆分類

            隨筆檔案

            搜索

            積分與排名

            最新評論

            閱讀排行榜

            評論排行榜

            精品综合久久久久久97超人 | 久久综合亚洲色一区二区三区| 69久久夜色精品国产69| 久久精品国产亚洲AV忘忧草18| 久久青青草原精品国产不卡| 国产AV影片久久久久久| 国产精品久久久天天影视| 丁香狠狠色婷婷久久综合| 好久久免费视频高清| 国产婷婷成人久久Av免费高清| 无码专区久久综合久中文字幕| 亚洲精品WWW久久久久久| 久久久久久久久久久精品尤物| 久久大香萑太香蕉av| 东方aⅴ免费观看久久av | 久久精品中文字幕第23页| 久久久99精品一区二区| 亚洲欧美精品一区久久中文字幕| 欧美久久一区二区三区| 国内精品伊人久久久久777| 久久综合亚洲欧美成人| 一本久久久久久久| 久久影院午夜理论片无码| 狠狠色丁香婷婷久久综合| 精品无码久久久久国产| 久久国产视屏| 久久久久亚洲AV无码网站| 欧美一区二区精品久久| 久久99九九国产免费看小说| 无码AV中文字幕久久专区| 成人亚洲欧美久久久久| 久久综合偷偷噜噜噜色| 91精品国产乱码久久久久久| 开心久久婷婷综合中文字幕| 久久久久久久亚洲Av无码| 久久久久国产视频电影| 久久99国产乱子伦精品免费| 精品久久久久久99人妻| 国产午夜免费高清久久影院| 久久综合狠狠综合久久97色| 77777亚洲午夜久久多喷|