需支援:圖片加框(可多層)、橫向拼接、縱向拼接。現實語意:一張圖片同一時刻只能呈現一種樣貌(要么加框、要么拼接),除非複製出新圖片。
因此圖片只需回應三條訊息:寬度、高度、第 N 行內容。所有裝飾行為均可透過攔截並轉發這三條訊息實現。
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 的訊息迴路:**無繼承、無虛函數、無動態派發開銷**,卻完美支援任意層級裝飾與組合。正如文中所云:「不管八風亂起,我自巋然不動」。