原書以裝飾、組合等多重模式解決「圖片加框、橫向/縱向拼接」問題,引入大量介面、虛函數、繼承層次。作者認為:每多一個模式就多一層間接層,偏離問題本質。本文採用「訊息傳遞」極簡風格,無繼承、無虛函數,核心僅 100 行左右。
enum { PM_WIDTH, PM_HEIGHT, PM_ROW };
struct PictureMsg {
using Proc = int(*)(void* pThis, int msg, void* p1, void* p2);
void* pThis;
Proc proc;
int GetWidth() { return proc(pThis, PM_WIDTH, nullptr, nullptr); }
int GetHeight() { return proc(pThis, PM_HEIGHT, nullptr, nullptr); }
int GetRow(int r, std::string& s) { return proc(pThis, PM_ROW, (void*)r, &s); }
};
// 輸出運算子:逐行取得字串並換行
std::ostream& operator<<(std::ostream& out, PictureMsg& msg) {
for (int r=0, h=msg.GetHeight(); r
class CPicture : public PictureMsg {
const char** data_; int count_, width_;
static int HandleMsg(void* pThis, int msg, void* p1, void* p2) {
auto self = (CPicture*)pThis;
switch (msg) {
case PM_WIDTH: return self->width_;
case PM_HEIGHT: return self->count_;
case PM_ROW: {
int r = (int)p1; auto& s = *(std::string*)p2;
if (r >= self->count_) break;
for (int i=0; self->data_[r][i]; ++i) s.push_back(self->data_[r][i]);
for (int i=s.size(); iwidth_; ++i) s.push_back(' ');
}
} return 0;
}
public:
CPicture(const char* d[], int n) : data_(d), count_(n), width_(0) {
for (int i=0;i
// 加框:攔截 WIDTH/HEIGHT/ROW,在外層添加 + - | 字元
class CFrameDecorater {
PictureMsg prev_;
static int HandleMsg(void* pThis, int msg, void* p1, void* p2) {
auto self = (CFrameDecorater*)pThis; auto& p = self->prev_;
switch (msg) {
case PM_WIDTH: return p.GetWidth() + 2;
case PM_HEIGHT: return p.GetHeight() + 2;
case PM_ROW: {
int r = (int)p1; auto& s = *(std::string*)p2;
if (r == 0 || r > p.GetHeight()) { // 頂/底框
s.push_back('+');
for (int i=0;ileft_.GetWidth() + self->right_.GetWidth();
case PM_HEIGHT: return std::max(self->left_.GetHeight(), self->right_.GetHeight());
case PM_ROW: {
int r = (int)p1; auto& s = *(std::string*)p2;
PrintRow(self->left_, r, s);
PrintRow(self->right_, r, s);
}
} return 0;
}
public:
CHorseDecorater(PictureMsg& L, PictureMsg& R) : left_(L), right_(R) {
L.pThis = this; L.proc = HandleMsg;
R.pThis = this; R.proc = HandleMsg;
}
};
int main() {
const char* pic[] = {"Paris","in the","Spring","HaHa"};
CPicture p1(pic, 3), p2(pic, 4);
CFrameDecorater f1(p1); // p1 加框
CFrameDecorater f2(p1); // p1 再加框(雙層)
CHorseDecorater h1(p1, p2); // p1 | p2
CFrameDecorater f3(p1); // 整體再加框
CHorseDecorater h2(p2, p1); // p2 | p1
CFrameDecorater f4(p2);
CHorseDecorater h3(p1, p2);
std::cout << p1; // 只印 p1,卻反映所有裝飾結果
}
CPicture 完全不知情,符合「開放封閉原則」;PM_CLONE 支援深拷貝);