设计模式之状态模式(State)摘录
State:(1)、意图:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
(2)、适用性:
A、一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
B、一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
(3)、相关模式:A、Flyweight模式解释了何时以及怎样共享状态对象。B、状态对象通常是Singleton。
(4)、当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,可考虑用到状态模式。
(5)、在State模式中,将状态逻辑和动作实现进行分离。当一个操作中要维护大量的case分支语句,并且这些分支依赖于对象的状态。State模式将每一个分支都封装到独立的类中。State模式和Strategy模式有很大程度上的相似:它们都有一个Context类,都是通过委托(组合)给一个具有多个派生类的多态基类实现Context的算法逻辑。两者最大的差别就是State模式重派生类持有指向Context对象的引用,并通过这个引用调用Context中的方法,但是Strategy模式中就没有这种情况。因此可以说一个State实例同样是Strategy模式的一个实例,反之却不成立。实际上State模式和Strategy模式的区别还在于它们所关注的点不尽相同:State模式主要是要适应对象对于状态改变时的不同处理策略的实现,而Strategy则主要是具体算法和实现接口的解耦(coupling),Strategy模式中并没有状态的概念(虽然很多时候可以被看作是状态的概念),并且更加不关心状态的改变了。State模式很好地实现了对象的状态逻辑和动作实现的分离,状态逻辑分布在State的派生类中实现,而动作实现则可以放在Context类中实现(这也是为什么State派生类需要拥有一个指向Context的指针)。这使得两者的变化相互独立,改变State的状态逻辑可以很容易复用Context的动作,也可以在不影响State派生类的前提下创建Context的子类来更改或替换动作实现。State模式问题主要是逻辑分散化,状态逻辑分布到了很大的State的子类中,很难看到整个的状态逻辑图,这也带来了代码的维护问题。
示例代码1:
#include <iostream> using namespace std; class Work; class ForenoonState; class NoonState; class State { public: virtual void WriteProgram(Work* w) = 0; }; class Work { private: State* current; public: double hour; public: Work(); void SetState(State* temp) { current = temp; } void Writeprogram() { current->WriteProgram(this); } }; class NoonState : public State { public: virtual void WriteProgram(Work* w) { cout<<"execute"<<endl; if ((w->hour) < 13) cout<<"还不错啦"<<endl; else cout<<"不行了,还是睡觉吧"<<endl; } }; class ForenoonState : public State { public: virtual void WriteProgram(Work* w) { if ((w->hour) < 12) cout<<"现在的精神无敌好"<<endl; else { w->SetState(new NoonState()); w->Writeprogram();//注意加上这句 } } }; Work::Work() { current = new ForenoonState(); } //客户端 int main() { Work* mywork = new Work(); mywork->hour = 9; mywork->Writeprogram(); mywork->hour = 14; mywork->Writeprogram(); /*result 现在的精神无敌好 execute 不行了,还是睡觉吧 */ return 0; } |
示例代码2:
State.h:
#ifndef _STATE_H_ #define _STATE_H_ class Context;//前置声明 class State { public: State(); virtual ~State(); virtual void OperationInterface(Context*) = 0; virtual void OperationChangeState(Context*) = 0; protected: bool ChangeState(Context* con, State* st); }; class ConcreteStateA : public State { public: ConcreteStateA(); virtual ~ConcreteStateA(); virtual void OperationInterface(Context*); virtual void OperationChangeState(Context*); protected: private: }; class ConcreteStateB : public State { public: ConcreteStateB(); virtual ~ConcreteStateB(); virtual void OperationInterface(Context*); virtual void OperationChangeState(Context*); protected: private: }; #endif//~_STATE_H_ |
State.cpp:
#include "State.h" #include "Context.h" #include <iostream> using namespace std; State::State() { } State::~State() { } void State::OperationInterface(Context* con) { cout<<"State:: ..."<<endl; } bool State::ChangeState(Context* con, State* st) { con->ChangeState(st); return true; } void State::OperationChangeState(Context* con) { } ConcreteStateA::ConcreteStateA() { } ConcreteStateA::~ConcreteStateA() { } void ConcreteStateA::OperationInterface(Context* con) { cout<<"ConcreteStateA::OperationInterface ..."<<endl; } void ConcreteStateA::OperationChangeState(Context* con) { OperationInterface(con); this->ChangeState(con, new ConcreteStateB()); } ConcreteStateB::ConcreteStateB() { } ConcreteStateB::~ConcreteStateB() { } void ConcreteStateB::OperationInterface(Context* con) { cout<<"ConcreteStateB::OperationInterface ..."<<endl; } void ConcreteStateB::OperationChangeState(Context* con) { OperationInterface(con); this->ChangeState(con, new ConcreteStateA()); } |
Context.h:
#ifndef _CONTEXT_H_ #define _CONTEXT_H_ class State; class Context { public: Context(); Context(State* state); ~Context(); void OperationInterface(); void OperationChangeState(); protected: private: friend class State;//表明在State类中可以访问Context类的private字段 bool ChangeState(State* state); private: State* _state; };#endif//~_CONTEXT_H_ |
Context.cpp:
#include "Context.h" #include "State.h" Context::Context() { } Context::Context(State* state) { this->_state = state; } Context::~Context() { delete _state; } void Context::OperationInterface() { _state->OperationInterface(this); } bool Context::ChangeState(State* state) { //_state->ChangeState(this, state); this->_state = state; return true; } void Context::OperationChangeState() { _state->OperationChangeState(this); } |
main.cpp:
#include "Context.h" #include "State.h" #include <iostream> using namespace std; int main() { State* st = new ConcreteStateA(); Context* con = new Context(st); con->OperationChangeState(); con->OperationChangeState(); con->OperationChangeState(); if (con != NULL) delete con; if (st != NULL) st = NULL; /*result ConcreteStateA::OperationInterface ... ConcreteStateB::OperationInterface ... ConcreteStateA::OperationInterface ... */ return 0; }
|
状态模式结构图:
设计模式之观察者模式(Observer)摘录
Observer:(1)、意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
(2)、适用性:
A、当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这两者封装在独立的对象中以使它们可以各自独立地改变和复用。
B、当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变。
C、当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合的。
(3)、优缺点:
A、目标和观察者间的抽象耦合:一个目标所知道的仅仅是它有一系列观察者,每个都符合抽象的Observer类的简单接口。目标不知道任何一个观察者属于哪一个具体的类。这样目标和观察者之间的耦合是抽象的和最小的。因为目标和观察者不是紧密耦合的,它们可以属于一个系统中的不同抽象层次。一个处于较低层次的目标对象可与一个处于较高层次的观察者通信并通知它,这样就保持了系统层次的完整。如果目标和观察者混在一块,那么得到的对象要么横贯两个层次(违反了层次性),要么必须放在这两层的某一层中(这可能会损害层次抽象)。
B、支持广播通信:不像通常的请求,目标发送的通知不需指定它的接收者。通知被自动广播给所有已向该目标对象登记的有关对象。目标对象并不关心到底有多少对象对自己感兴趣;它唯一的责任就是通知它的各观察者。这给了你在任何时刻增加和删除观察者的自由。处理还是忽略一个通知取决于观察者。
C、意外的更新:因为一个观察者并不知道其它观察者的存在,它可能对改变目标的最终代价一无所知。在目标上一个看似无害的操作可能会引起一系列对观察者以及依赖于这些观察者的那些对象的更新。此外,如果依赖准则的定义或维护不当,常常会引起错误的更新,这种错误通常很难捕捉。简单的更新协议不提供具体细节说明目标中什么被改变了,这就使得上述问题更加严重。如果没有其他协议帮助观察者发现什么发生了改变,它们可能会被迫尽力减少改变。
(4)、相关模式:A、Mediator:通过封装复杂的更新语义,ChangeManager(当目标和观察者间的依赖关系特别复杂时,可能需要一个维护这些关系的对象。我们称这样的对象为更改管理器。它的目的是尽量减少观察者反映其目标的状态变化所需的工作量)
充当目标和观察者之间的中介者。B、Singleton:ChangeManager可使用Singleton模式来保证它是唯一的并且是可全局访问的。
(5)、观察者模式:定义了一种一对多的关系,让多个观察对象同时监听一个主题对象,主题对象状态发生变化时,会通知所有的观察者,使它们能够更新自己。
(6)、Observer模式要解决的问题为:建立一个一(Subject)对多(Observer)的依赖关系,并且做到当“一”变化的时候,依赖这个”一”的多也能够同步改变。最常见的一个例子就是:对同一组数据进行统计分析的时候,我们希望能够提供多种形式的表示(例如以表格进行统计显示、柱状图统计显示、百分比统计显示等)。这些表示都依赖于同一组数据,我们当然需要当数据改变的时候,所有的统计的显示都能够同时改变。Observer模式就是解决了这一关问题。
示例代码1:
#include <string> #include <iostream> #include <vector> using namespace std; class Secretary; //看股票的同事类(观察对象,观察者) class StockObserver { private: string name; Secretary* sub; public: StockObserver(string strname, Secretary* strsub) { name = strname; sub = strsub; } void Update(); }; //秘书类(主题对象,通知者) class Secretary { private: vector<StockObserver> observers; public: string action; void Add(StockObserver ob) { observers.push_back(ob); } void Notify() { vector<StockObserver>::iterator p = observers.begin(); while (p != observers.end()) { (*p).Update(); p ++; } } }; void StockObserver::Update() { cout<<name<<":"<<sub->action<<",不要玩股票了,要开始工作了"<<endl; } //客户端 int main() { Secretary* p = new Secretary();//创建通知者 //观察者 StockObserver* s1 = new StockObserver("小李", p); StockObserver* s2 = new StockObserver("小赵", p); //加入通知队列 p->Add(*s1); p->Add(*s2); //事件 p->action = "老板来了"; //通知 p->Notify(); /*result 小李:老板来了,不要玩股票了,要开始工作了 小赵:老板来了,不要玩股票了,要开始工作了 */ return 0; } |
示例代码2:
#include <string> #include <iostream> #include <vector> using namespace std; class SecretaryBase; //抽象观察者 class CObserverBase { protected: string name; SecretaryBase* sub; public: CObserverBase(string strname, SecretaryBase* strsub) { name = strname; sub = strsub; } virtual void Update() = 0; }; //具体的观察者,看股票的 class StockObserver : public CObserverBase { public: StockObserver(string strname, SecretaryBase* strsub) : CObserverBase(strname, strsub) { } virtual void Update(); }; //具体观察者,看NBA的 class NBAObserver : public CObserverBase { public: NBAObserver(string strname, SecretaryBase* strsub) : CObserverBase(strname, strsub) { } virtual void Update(); }; //抽象通知者 class SecretaryBase { public: string action; vector<CObserverBase*> observers; public: virtual void Attach(CObserverBase* observer) = 0; virtual void Notify() = 0; }; //具体通知者 class Secretary : public SecretaryBase { public: void Attach(CObserverBase* ob) { observers.push_back(ob); } void Notify() { vector<CObserverBase*>::iterator p = observers.begin(); while (p != observers.end()) { (*p)->Update(); p ++; } } }; void StockObserver::Update() { cout<<name<<":"<<sub->action<<"不要玩股票了,要开始工作了"<<endl; } void NBAObserver::Update() { cout<<name<<":"<<sub->action<<"不要看NBA了,老板来了"<<endl; } //客户端 int main() { SecretaryBase* p = new Secretary();//创建观察者 //被观察的对象 CObserverBase* s1 = new NBAObserver("小李", p); CObserverBase* s2 = new StockObserver("小赵", p); //加入观察队列 p->Attach(s1); p->Attach(s2); //事件 p->action = "老板来了"; //通知 p->Notify(); /*result 小李:老板来了不要看NBA了,老板来了 小赵:老板来了不要玩股票了,要开始工作了 */ return 0; } |
示例代码3:
Subject.h:
#ifndef _SUBJECT_H_ #define _SUBJECT_H_ #include <list> #include <string> using namespace std; typedef string State; class Observer; class Subject { public: virtual ~Subject(); virtual void Attach(Observer* obv); virtual void Detach(Observer* obv); virtual void Notify(); virtual void SetState(const State& st) = 0; virtual State GetState() = 0; protected: Subject(); private: list<Observer*>* _obvs; }; class ConcreteSubject : public Subject { public: ConcreteSubject(); ~ConcreteSubject(); State GetState(); void SetState(const State& st); protected: private: State _st; };#endif//~_SUBJECT_H_ |
Subject.cpp:
#include "Subject.h" #include "Observer.h" #include <iostream> #include <list> using namespace std; typedef string state; Subject::Subject() { //在模板的使用之前一定要new,创建 _obvs = new list<Observer*>; } Subject::~Subject() { } void Subject::Attach(Observer* obv) { _obvs->push_front(obv); } void Subject::Detach(Observer* obv) { if (obv != NULL) _obvs->remove(obv); } void Subject::Notify() { list<Observer*>::iterator it; it = _obvs->begin(); for (; it != _obvs->end(); it ++) //关于模板和iterator的用法 (*it)->Update(this); } ConcreteSubject::ConcreteSubject() { _st = '\0'; } ConcreteSubject::~ConcreteSubject() { } State ConcreteSubject::GetState() { return _st; } void ConcreteSubject::SetState(const State& st) { _st = st; } |
Observer.h:
#ifndef _OBSERVER_H_ #define _OBSERVER_H_ #include "Subject.h" #include <string> using namespace std; typedef string State; class Observer { public: virtual ~Observer(); virtual void Update(Subject* sub) = 0; virtual void PrintInfo() = 0; protected: Observer(); State _st; private: }; class ConcreteObserverA : public Observer { public: virtual Subject* GetSubject(); ConcreteObserverA(Subject* sub); virtual ~ConcreteObserverA(); //传入Subject作为参数,这样可以让一个View属于多个的Subject void Update(Subject* sub); void PrintInfo(); protected: private: Subject* _sub; }; class ConcreteObserverB : public Observer { public: virtual Subject* GetSubject(); ConcreteObserverB(Subject* sub); virtual ~ConcreteObserverB(); //传入Subject作为参数,这样可以让一个View属于多个的Subject void Update(Subject* sub); void PrintInfo(); protected: private: Subject* _sub; }; #endif//~_OBSERVER_H_ |
Observer.cpp:
#include "Observer.h" #include "Subject.h" #include <iostream> #include <string> using namespace std; Observer::Observer() { _st = '\0'; } Observer::~Observer() { } ConcreteObserverA::ConcreteObserverA(Subject* sub) { _sub = sub; _sub->Attach(this); } ConcreteObserverA::~ConcreteObserverA() { _sub->Detach(this); if (_sub != 0) delete _sub; } Subject* ConcreteObserverA::GetSubject() { return _sub; } void ConcreteObserverA::PrintInfo() { cout<<"ConcreteObserverA observer ..."<<_sub->GetState()<<endl; } void ConcreteObserverA::Update(Subject* sub) { _st = sub->GetState(); PrintInfo(); } ConcreteObserverB::ConcreteObserverB(Subject* sub) { _sub = sub; _sub->Attach(this); } ConcreteObserverB::~ConcreteObserverB() { _sub->Detach(this); if (_sub != 0) delete _sub; } Subject* ConcreteObserverB::GetSubject() { return _sub; } void ConcreteObserverB::PrintInfo() { cout<<"ConcreteObserverB observer ..."<<_sub->GetState()<<endl; } void ConcreteObserverB::Update(Subject* sub) { _st = sub->GetState(); PrintInfo(); } |
main.cpp:
#include "Subject.h" #include "Observer.h" #include <iostream> using namespace std; int main() { ConcreteSubject* sub = new ConcreteSubject(); Observer* o1 = new ConcreteObserverA(sub); Observer* o2 = new ConcreteObserverB(sub); sub->SetState("old"); sub->Notify(); sub->SetState("new");//也可以由Observer调用 sub->Notify(); /*result ConcreteObserverB observer ...old ConcreteObserverA observer ...old ConcreteObserverB observer ...new ConcreteObserverA observer ...new */ return 0; } |
观察者模式结构图:
|