消息发送VS设计模式 C++沉思录的一练习题的另解
缘起,看到一遍文章,题材取自于《C++沉思录》,综合利用好几种设计模式,并且结合所谓的面向对象的技巧,然后洋洋自得,并且在最后,还反问:“有更好的解决方案吗?”。本座暗叹,又一个设计模式的毒害者。以下,就提出另一种解决方案。首先,先声明一点,现实中,一张图片,可以给予添加一层又一层片框,也可以和其他的图片组合在一块,或横,或竖,……,但是,图片,始终只有一张,对它处理之后,它就一直是那个样子了,不可能同时看到它的两个样子,或加边框,或和其他照片组合在一块。如果,拿这张图片去进行复制,那又自是另当别论,但那已经是另外一第图片了。当然,对以下例子稍加修改,就能支持修饰的图片的复制操作。
本座最近在写一套消息框架,如果这个例子能用上那套框架,写起来就会很简单。但是,即使没有消息框架的支持,利用消息发送来解决这个问题,也是相当小儿科的事情。为了突出重点,忽略了各种异常处理,没有优化,也不管什么编程风格,纯粹直奔主题。解决这个例子的最重要一点,就在于打印图片时,要一行一行地从顶到底顺次打印下来。 www.zzzyk.com
typedef int (*ProcPictureImp)(void* pThis, int nMessage, void* param1, void* param2);
enum { PM_WIDTH, PM_HEIGHT, PM_PRINT_ROW};
struct PictureImp
{
void* pThis;
ProcPictureImp proc;
int GetWidth()
{
return (*proc)(pThis, PM_WIDTH, NULL, NULL);
}
int GetHeight()
{
return (*proc)(pThis, PM_HEIGHT, NULL, NULL);
}
int PrintRow(int nRow, ostream& out)
{
return (*proc)(pThis, PM_PRINT_ROW, (void*)nRow, (void*)&out);
}
};
class CPicture
{
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;
}
m_Imp.pThis = this;
m_Imp.proc = HandleMsg;
}
void Print(ostream& out);
public:
PictureImp m_Imp;
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_PRINT_ROW:
int nRow = (int)param1;
ostream& out = *(ostream*)param2;
if (nRow >= pSelf->m_nCount)
break;
int i=0;
for (; pSelf->m_pDatas[nRow][i] != 0; i++)
out << pSelf->m_pDatas[nRow][i];
for (; i<pSelf->m_nWidth; i++)
out << ' ';
}
return 0;
}
void CPicture::Print(ostream& out)
{
int nHeight = m_Imp.GetHeight();
for (int nRow = 0; nRow<nHeight; nRow++)
{
m_Imp.PrintRow(nRow, out);
out << endl;
}
}
class CFrameDecorater
{
public:
CFrameDecorater(PictureImp& imp)
{
m_PrevImp = imp;
imp.pThis = this;
imp.proc = HandleMsg;
}
private:
PictureImp 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;
PictureImp& prevImp = pSelf->m_PrevImp;
switch (nMessage)
{
case PM_WIDTH:
return prevImp.GetWidth()+2;
case PM_HEIGHT:
return prevImp.GetHeight()+2;
case PM_PRINT_ROW:
int nRow = (int)param1;
ostream& out = *(ostream*)param2;
bool bMyRow = nRow == 0 || nRow>prevImp.GetHeight();
if (nRow >= prevImp.GetWidth()+2)
break;
if (nRow == 0 || nRow>prevImp.GetHeight())
{
out << '+';
for (int i=0; i<prevImp.GetWidth(); i++)
out << '-';
out << '+';
}
else
{
out << '|';
prevImp.PrintRow(nRow-1, out);
&nb
补充:软件开发 , C语言 ,