Command and Observer

1.Observer(观察者模式)

主题对象管理某些数据,当主题内的数据发生改变,就通知观察者,观察者已经注册主题便会在主题数据发生改变时能够收到更新。一旦数据改变,新的数据会以某种形式送到观察者手上。
观察者模式定义了对象之间的一对多关系,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
![](http://codeplanet-wordpress.stor.sinaapp.com/uploads/2014/01/wpid-4056175e6cecd785cac776067999cc1e_obsv1.jpg)
例子:
#**include** <iostream> #**include** <set> #**include** <string> **using** **namespace** std; /////////////////////抽象模式定义 **class** CObservable; //观察者,纯虚基类 **class** CObserver { **public**: CObserver::CObserver(){}; **virtual** CObserver::~CObserver(){}; //当被观察的目标发生变化时,通知调用该方法 //来自被观察者pObs, 扩展参数为pArg **virtual** **void** Update(CObservable* pObs, **void*** pArg = NULL) = 0; }; //被观察者,即Subject **class** CObservable { **public**: CObservable() : m_bChanged(**false**) {}; **virtual** ~CObservable() {}; //注册观察者 **void** Attach(CObserver* pObs); //注销观察者 **void** Detach(CObserver* pObs); //注销所有观察者 **void** DetachAll(); //若状态变化,则遍历观察者,逐个通知更新 **void** Notify(**void*** pArg = NULL); //测试目标状态是否变化 **bool** HasChanged(); //获取观察者数量 **int** GetObserversCount(); **protected**: //设置状态变化!!!必须继承CObservable才能设置目标状态 **void** SetChanged(); //初始化目标为未变化状态 **void** ClearChanged(); **private**: **bool** m_bChanged; //状态 set<CObserver*> m_setObs; //set保证目标唯一性 }; /////////////////////抽象模式实现 **void** CObservable::Attach(CObserver* pObs) { **if** (!pObs) **return**; m_setObs.insert(pObs); } **void** CObservable::Detach(CObserver* pObs) { **if** (!pObs) **return**; m_setObs.erase(pObs); } **void** CObservable::DetachAll() { m_setObs.clear(); } **void** CObservable::SetChanged() { m_bChanged = **true**; } **void** CObservable::ClearChanged() { m_bChanged = **false**; } **bool** CObservable::HasChanged() { **return** m_bChanged; } **int** CObservable::GetObserversCount() { **return** m_setObs.size(); } **void** CObservable::Notify(**void*** pArg /* = NULL */) { **if** (!HasChanged()) **return**; cout << "notify observers…" << endl; ClearChanged(); set<CObserver*>::iterator itr = m_setObs.begin(); **for** (; itr != m_setObs.end(); itr++) { (*itr)->Update(**this**, pArg); } } /////////////////////具体应用类定义和实现 //bloger是发布者,即被观察者(subject) **class** CBloger : **public** CObservable { **public**: **void** Publish(**const** string &strContent) { cout << "bloger publish, content: " << strContent << endl; SetChanged(); Notify(**const_cast**<**char***>(strContent.c_str())); } }; //portal是发布者,即被观察者(subject) **class** CPortal : **public** CObservable { **public**: **void** Publish(**const** string &strContent) { cout << "portal publish, content: " << strContent << endl; SetChanged(); Notify(**const_cast**<**char***>(strContent.c_str())); } }; //RSS阅读器,观察者 **class** CRSSReader : **public** CObserver { **public**: CRSSReader(**const** string &strName) : m_strName(strName){} **virtual** **void** Update(CObservable* pObs, **void*** pArg = NULL) { **char*** pContent = **static_cast**<**char***>(pArg); //观察多个目标 **if** (**dynamic_cast**<CBloger*>(pObs)) { cout << m_strName << " updated from bloger, content: " << pContent << endl; } **else** **if** (**dynamic_cast**<CPortal*>(pObs)) { cout << m_strName << " updated from portal, content: " << pContent << endl; } } **private**: string m_strName; }; //Mail阅读器,观察者 **class** CMailReader : **public** CObserver { **public**: CMailReader(**const** string &strName) : m_strName(strName){} **virtual** **void** Update(CObservable* pObs, **void*** pArg = NULL) { **char*** pContent = **static_cast**<**char***>(pArg); **if** (**dynamic_cast**<CBloger*>(pObs)) { cout << m_strName << " updated from bloger, content: " << pContent << endl; } **if** (**dynamic_cast**<CPortal*>(pObs)) { cout << m_strName << " updated from portal, content: " << pContent << endl; } } **private**: string m_strName; }; /////////////////Main **int** main() { //目标(被观察者) CBloger* pBloger = **new** CBloger(); CPortal* pPortal = **new** CPortal(); //观察者. 一个观察者可以观察多个目标 CRSSReader* pRssReader = **new** CRSSReader("rss reader"); CMailReader* pMailReader = **new** CMailReader("mail reader"); pBloger->Attach(pRssReader); //bloger注册观察者 pBloger->Attach(pMailReader); //bloger注册观察者 pPortal->Attach(pRssReader); //portal注册观察者 pPortal->Attach(pMailReader); //portal注册观察者 //博客发布信息 pBloger->Publish("博客分享设计模式"); cout << endl; //门户发布信息 pPortal->Publish("门户分享设计模式"); cout << "\nportal detached mail reader" << endl; pPortal->Detach(pMailReader); cout << "portal observers count: " << pPortal->GetObserversCount() << endl << endl; pPortal->Publish("门户分享设计模式"); system("pause"); **return** 0; }
**2.Command(命令模式)**
命令模式通俗的例子:在餐厅,顾客订餐,把订单交给女招待,女招待拿了订单,交给厨师,厨师根据订单准备食物。一张订单封装了准备食物的请求。女招待的工作就是接受订单,然后调用订单的orderUp()方法。
命令模式,将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。
![](http://codeplanet-wordpress.stor.sinaapp.com/uploads/2014/01/wpid-4056175e6cecd785cac776067999cc1e_cmd1.jpg)
示例代码:
#**include** <iostream> #**include** <vector> **using** **namespace**std;// 烤肉师傅 **class** RoastCook { **public**: **void** MakeMutton() { cout << "烤羊肉" <<endl; }**void** MakeChickenWing() { cout << "烤鸡翅膀" << endl; } }; // 抽象命令类 **class** Command { **public**: Command(RoastCook* temp) { receiver = temp; } **virtual** **void** ExecuteCmd() = 0; **protected**: RoastCook* receiver; }; // 烤羊肉命令 **class** MakeMuttonCmd : **public** Command { **public**: MakeMuttonCmd(RoastCook* temp) : Command(temp) {} **virtual** **void** ExecuteCmd() { receiver->MakeMutton(); } }; // 烤鸡翅膀命令 **class** MakeChickenWingCmd : **public** Command { **public**: MakeChickenWingCmd(RoastCook* temp) : Command(temp) {} **virtual** **void** ExecuteCmd() { receiver->MakeChickenWing(); } }; // 服务员类 **class** Waiter { **public**: **void** SetCmd(Command* temp); // 通知执行 **void** Notify(); **protected**: vector<Command*> m_commandList; }; **void** Waiter::SetCmd(Command* temp) { m_commandList.push_back(temp); cout << "增加订单" << endl; } **void** Waiter::Notify() { vector<Command*>::iterator it; **for** (it=m_commandList.begin(); it!=m_commandList.end(); ++it) { (*it)->ExecuteCmd(); } } **int** main() { // 店里添加烤肉师傅、菜单、服务员等顾客 RoastCook* cook = **new** RoastCook(); Command* cmd1 = **new** MakeMuttonCmd(cook); Command* cmd2 = **new** MakeChickenWingCmd(cook); Waiter* girl = **new** Waiter(); // 点菜 girl->SetCmd(cmd1); girl->SetCmd(cmd2); // 服务员通知 girl->Notify(); system("pause"); **return** 0; }
**3.Command 和 Observer 的一些区别**
1.Command封装一个请求对象,Observer定义一种一对多的依赖关系;
2.Command通过对象解耦,Observer可以通过消息解耦;
3.Command可以有执行和撤消操作,所以从某种意义上来说,Command是有序的,Observer是无序的;
4.Command是在主类中通过接口调用各客户端子类的功能,Observer支持主类将更新通知给客户端,然后由客户端自行处理。
[参考]:http://www.cnblogs.com/Random/archive/2012/03/21/2409090.html
坚持原创技术分享,您的支持将鼓励我继续创作!