场景:
根据自己的理解和书上的例子假设了这样的场景
在一个程序中, 按F1, 程序显示出鼠标所在的区域的帮助信息.
例如鼠标在对话框的左上角区域, 则显示对话框的帮助信息XXX. 鼠标在对话框的左上角区域的按钮上时, 也是显示对话框的帮助信息XXX. (总之是在鼠标的左上角上, 无论在不在控件上)
角色:
CMyAPP 程序类, 控制整个程序的运行
CMyDialog 对话框类, 在CMyAPPlive上实例化. CMyDialog中包含各种控件(CMyButton, CMyEdit)
CMyButton 按钮控件, 在CMyDialog上实例化.
CMyEdit 编辑框控件, 在CMyDialog上实例化.
显示帮助信息, 使用Chain Of Responsibility模式, 在Chain Of Responsibility模式中, CMyDialog与控件之间的包含关系可以使用Composite模式.
如图:
图1
代码:
class HelpHandler
{
public:
HelpHandler();
virtual ~HelpHandler();
virtual void HandleHelp();
void SetNextHandleHelp(HelpHandler* pHelpHandler);
private:
HelpHandler* m_pNextHelpHandler;
}
...
void HelpHandler::HandleHelp()
{
if(m_pNextHelpHandler)
{
m_pNextHelpHandler->HandleHelp();
}
}
void HelpHandler::SetNextHandleHelp(HelpHandler* pHelpHandler)
{
m_pNextHelpHandler = pHelpHandler;
}
///
class CMyWnd
{
public:
CMyWnd();
virtual ~CMyWnd();
virtual void HandleHelp();
}
...
void CMyWnd::HandleHelp()
{
HelpHandler::HandleHelp();
}
///
class CMyDialog
{
public:
CMyDialog();
virtual ~CMyDialog();
virtual void HandleHelp();
void MyShowHelp1();
void MyShowHelp2();
private:
CMyButton* m_pCMyButton;
CMyEdit* m_pCMyEdit;
}
CMyDialog::CMyDialog()
{
// 生成责任链(m_pCMyButton -->>> m_pCMyEdit -->>> this)
m_pCMyButton = new CMyButton;
m_pCMyEdit = new CMyEdit;
m_pCMyButton->SetNextHandleHelp(m_pCMyEdit);
m_pCMyEdit->SetNextHandleHelp(this);
}
void CMyDialog::HandleHelp()
{
// Show Help Information
::MessageBox(.....);
// 责任人链到这里结束.
// 这里没有判断m_pNextHelpHandler, 让HandleHelp继续下去了.
}
// 触发
void CMyDialog::MyShowHelp1()
{
m_pCMyButton->HandleHelp();
}
// 触发
void CMyDialog::MyShowHelp2()
{
m_pCMyEdit->HandleHelp();
}
///
class CMyButton
{
public:
CMyButton();
virtual ~CMyButton();
}
...
class CMyEdit
{
public:
CMyEdit();
virtual ~CMyEdit();
}
...
///
在这里调用时, 如果鼠标触发到CMyDialog的调用时, 将会调用void CMyDialog::MyShowHelp1()或void CMyDialog::MyShowHelp(), 如果直接触发到CMyButton或者CMyEdit, 则将会调用CMyWnd::HandleHelp()
//
我的理解:
1. 在继承方向上(HelpHandler >>> CMyWnd >>> (CMyDialog, CMyButton, CMyEdit))通过重载HandleHelp, 可以在纵向把HandleHelp连接起来. 例如: 在CMyButton::HandleHelp可以不做任何东西, 也可以做一些东西, 然后传递给它的父类CMyWnd::HandleHelp, 也可以不传递.
2. 在责任链方向上, 这里是(CMyButton -->>> CMyEdit -->>> CMyDialog), 通过责任链, 横向的把HandleHelp连接起来. 例如CMyButton可以处理一些事情, 也可以不处理, 然后传递给它的下家, 而且通过责任链, 责任链上的对象并不需要和它的下家的类耦合在一起(CMyButton并不需要知道CMyEdit和CMyDialog)
3. 我理解是, 如果说继承链上的重载叫纵向重载, 责任链是不是可以叫"横向重载"(看一看图1)
4. 在该场景中, 责任链的责任关系是静态的, 因为代码把这种关系固定下来的了, 就是CMyDialog负责处理帮助信息, CMyButton和CMyEdit只负责传递给它的下家, 而不作其它任何处理, 当然, 责任链上的对象是可以动态的(例如: 运行时, 责任两CMyButton对象|CMyEdit对象|CMyButton对象|CMyDialog对象| )
5. 责任链的责任关系也可以使动态的, 增加请求类型即可, 在自己的HandleHelp判断请求类型来判断是否处理还是向下传递.
6. 注意责任链的构造(看CMyDialog::CMyDialog()的实现)
7. 在这里, 没有使用上Composite模式, 因为责任链最终的处理都是在CMyDialog::HandleHelp()上, 如果使用Composite模式就会死循环了.
例如Composite模式的话就是这样了
void CMyDialog::HandleHelp()
{
m_pCMyButton->HandleHelp();
m_pCMyEdit->HandleHelp();
}
只能说这个场景不适合使用Composite模式, 如果是最终是在CMyApp::HandleHelp处理的话就可以, 总之就是不能死循环.
8. 不使用继承, 使用包含可以吗?
我的理解是这样:
图2
每个类多了一个HelpHandler类, 在各个HelpHandler类中还是用到了继承关系. HelpHandler类在各自对应的类中创建(使用某创建模式).