首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

訊息傳遞 VS 設計模式:C++ 沉思錄練習題的極簡另解

     編輯:關於C語言

問題重述

需支援:圖片加框(可多層)、橫向拼接、縱向拼接。現實語意:一張圖片同一時刻只能呈現一種樣貌(要么加框、要么拼接),除非複製出新圖片。

核心洞察:列印必須逐行自上而下

因此圖片只需回應三條訊息:寬度、高度、第 N 行內容。所有裝飾行為均可透過攔截並轉發這三條訊息實現。

極簡訊息框架(約 50 行)

enum { PM_WIDTH, PM_HEIGHT, PM_PRINT_ROW };

struct PictureImp {
    using Proc = int(*)(void*, int, void*, void*);
    void* pThis; Proc proc;
    int GetWidth()  { return proc(pThis, PM_WIDTH,  nullptr, nullptr); }
    int GetHeight() { return proc(pThis, PM_HEIGHT, nullptr, nullptr); }
    int PrintRow(int r, std::ostream& os) { return proc(pThis, PM_PRINT_ROW, (void*)r, &os); }
};

// 基礎圖片
class CPicture {
    const char** d_; int n_, w_;
    PictureImp imp_;
    static int Handle(void* th, int msg, void* p1, void* p2) {
        auto s=(CPicture*)th; std::ostream& os=*(std::ostream*)p2;
        switch(msg){
            case PM_WIDTH: return s->w_;
            case PM_HEIGHT: return s->n_;
            case PM_PRINT_ROW: {
                int r=(int)p1; if(r>=s->n_) break;
                for(int i=0;s->d_[r][i];++i) os<d_[r][i];
                for(int i=strlen(s->d_[r]);iw_;++i) os<<' ';
            }
        } return 0;
    }
public:
    CPicture(const char* d[], int n):d_(d),n_(n),w_(0){
        for(int i=0;i

裝飾器:攔截訊息、轉發、修改

// 加框
class CFrameDecorater {
    PictureImp prev_;
    static int Handle(void* th, int msg, void* p1, void* p2) {
        auto s=(CFrameDecorater*)th; auto& p=s->prev_; std::ostream& os=*(std::ostream*)p2;
        switch(msg){
            case PM_WIDTH: return p.GetWidth()+2;
            case PM_HEIGHT: return p.GetHeight()+2;
            case PM_PRINT_ROW: {
                int r=(int)p1;
                if(r==0 || r>p.GetHeight()){ os<<'+'; for(int i=0;iL_.GetWidth()+s->R_.GetWidth();
            case PM_HEIGHT: return std::max(s->L_.GetHeight(), s->R_.GetHeight());
            case PM_PRINT_ROW: { int r=(int)p1; Row(s->L_,r,os); Row(s->R_,r,os); }
        } return 0;
    }
public:
    CHorseDecorater(PictureImp& L, PictureImp& R):L_(L),R_(R){
        L.pThis=this; L.proc=Handle; R.pThis=this; R.proc=Handle;
    }
};

使用範例

int main(){
    const char* d[]={"Paris","in the","Spring","HaHa"};
    CPicture p1(d,3), p2(d,4);
    p1.Print(std::cout);
    CFrameDecorater f1(p1.Imp());
    CFrameDecorater f2(p1.Imp());
    CHorseDecorater h1(p1.Imp(), p2.Imp());
    CFrameDecorater f3(p1.Imp());
    CHorseDecorater h2(p2.Imp(), p1.Imp());
    CFrameDecorater f4(p2.Imp());
    CHorseDecorater h3(p1.Imp(), p2.Imp());
    p1.Print(std::cout);   // 依然印 p1,卻呈現所有裝飾疊加結果
}

結語

這本質上是模仿 Windows 視窗程序 WndProc 的訊息迴路:**無繼承、無虛函數、無動態派發開銷**,卻完美支援任意層級裝飾與組合。正如文中所云:「不管八風亂起,我自巋然不動」。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved