设计模式
人类社会中和自然界中的各种组织结构和活动是不断演变和进化而来的,他们的存在是具有一定的合理性和鲁棒性。然而软件的诞生只有区区几十年的时间,其结构和开发方法不尽完善,故模拟现实生活中的场景成为一个有效的手段。建筑工程和软件工程,树图和数据结构……
我们将通过类比现实生活中大家都熟悉的结构或活动来理解设计模式,并给出可运行得代码。
1. 职责链
1.1. 现实场景
举一个申冤例子。假设你有个冤情。最先找到村委会,如果这个请求属于其职责范围之内并且可以得到圆满解决,那么申冤到此结束,否则会被传递到镇政府。同理如果这个请求在其职责范围并且可以给你满意的答复,申冤到此结束,否则再到市政府。依次类推,可能一直到中央。这就所谓的“到京城告御状”。
对应于软件的职责链,“申冤”对应于“发出一个请求”,各个不同级别的“政府部门”对应于请求的潜在“相应者”。伸冤者事先并不知道哪个部门可以解决他的冤情。所以依次传递直到得到满意的解决或答复。
1.2. 示例代码
#include <iostream> using namespace std;
typedef int Topic;
const Topic NO_HELP_TOPIC = -1; const Topic PRINT_TOPIC = 1; const Topic PAPER_RIENTATION_TOPIC =2; const Topic APPLICATION_TOPIC =3;
class HelpHandler { public: HelpHandler(HelpHandler* = 0, Topic = NO_HELP_TOPIC); virtual bool HasHelp(); virtual void SetHandler(HelpHandler*, Topic); virtual void HandleHelp(); virtual Topic GetTopic();
private: HelpHandler* _successor; Topic _topic; };
HelpHandler::HelpHandler(HelpHandler* h, Topic t): _successor(h), _topic(t){}
bool HelpHandler::HasHelp() { return _topic != NO_HELP_TOPIC; }
void HelpHandler::HandleHelp() { if(_successor != 0) { _successor->HandleHelp(); } }
void HelpHandler::SetHandler(HelpHandler* h, Topic t) { _successor = h; _topic = t; } Topic HelpHandler::GetTopic() { return _topic; }
class Widget : public HelpHandler { protected: Widget(Widget* parent, Topic = NO_HELP_TOPIC); private: Widget* _parent; };
Widget::Widget(Widget* w, Topic t) : HelpHandler(w, t) { _parent =w; }
class Button : public Widget { public: Button(Widget* d, Topic t = NO_HELP_TOPIC); virtual void HandleHelp(); };
Button::Button (Widget* h, Topic t) : Widget(h, t) {}
void Button::HandleHelp() { if(HasHelp()) { cout<<"button help/n"; } else { HelpHandler::HandleHelp(); } }
class Dialog : public Widget { public: Dialog(HelpHandler* h, Topic t = NO_HELP_TOPIC); virtual void HandleHelp(); };
Dialog::Dialog (HelpHandler* h, Topic t) : Widget(0) { SetHandler(h, t); }
void Dialog::HandleHelp(){ switch(GetTopic()) { case PAPER_RIENTATION_TOPIC: cout<<"paper rientation /n"; break; case PRINT_TOPIC: cout<<"print /n"; break; default: HelpHandler::HandleHelp(); } }
class Application : public HelpHandler { public: Application(Topic t):HelpHandler(0, t) {}; virtual void HandleHelp(); };
void Application::HandleHelp () { cout<<"app help list/n"; }
/*
chain of resposibility [button] ---> [dialog] ---> [application]
*/ int main() { //button deal with help request Application* application = new Application(APPLICATION_TOPIC); Dialog* dialog = new Dialog(application, PRINT_TOPIC); Button* button = new Button(dialog, PAPER_RIENTATION_TOPIC); button->HandleHelp();
//dialog deal with help request button->SetHandler(dialog, NO_HELP_TOPIC); button->HandleHelp();
//application deal with help request dialog->SetHandler(application, NO_HELP_TOPIC); button->HandleHelp();
return 0; }
|