设计模式——行为型模式(一)
行为模式涉及到算法和对象间职责的分配。行为模式不仅描述对象或类的模式,还描述他们之间的通信模式,这些模式刻画了在运行时难以跟踪的复杂的控制流。
行为类模式使用继承机制在类间分派行为;行为对象模式使用对象复合而不是继承。
1. TemplateMethod——类行为模式
作用:
定义一个操作中算法的骨架,而将一些步骤延迟到子类中。TemplateMethod使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
UML结构图:
抽象基类:
AbstractClass 定义算法的轮廓
解析:
TemplateMethod的关键在于基类中定义了一个算法的轮廓,但是算法每一步具体的实现留给了派生类。这样也会造成设计的灵活性不高的缺点,因为轮廓已经定下来了想要改变就困难了,这也是为什么优先使用组合而不是继承的原因。
实现:
typedef string STATE; class Flyweight { public: virtual ~Flyweight(){} STATE GetIntrinsicState() { return m_State; } virtual void Operation(STATE& ExtrinsincState)=0; protected: Flyweight(const STATE& state):m_State(state){} private: STATE m_State; }; class ConcreteFlyweight:public Flyweight { public: ConcreteFlyweight(const STATE& state):Flyweight(state){} virtual ~ConcreteFlyweight(){} virtual void Operation(STATE& ExtrinsicState){} }; class FlyweightFactory { public: FlyweightFactory(){} ~FlyweightFactory() { list<Flyweight*>::iterator iter1,iter2,temp; for(iter1=m_listFlyweight.begin(),iter2=m_listFlyweight.end(); iter1!=iter2;) { temp = iter1; ++iter1; delete (*temp); } m_listFlyweight.clear(); } Flyweight* GetFlyweight(const STATE& key) { list<Flyweight*>::iterator iter1,iter2; for(iter1=m_listFlyweight.begin(),iter2=m_listFlyweight.end(); iter1!=iter2;++iter1) { if((*iter1)->GetIntrinsicState()==key) { cout<<"The Flyweight:"<<key<<"already exists"<<endl; return (*iter1); } cout<<"Creating a new Flyweight:"<<key<<endl; Flyweight* flyweight = new ConcreteFlyweight(key); m_listFlyweight.push_back(flyweight); } } private: list<Flyweight*> m_listFlyweight; }; int main() { FlyweightFactory* fly = new FlyweightFactory(); fly->GetFlyweight("hello"); fly->GetFlyweight("world"); fly->GetFlyweight("hello"); return 0; }
2. Chain of responsibility——对象行为型模式
作用:
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
UML结构图:
抽象基类:
Handler 定义一个处理请求的接口,在图中这个接口就是HanleRequest函数,这个类同时有一个指向Handler对象的指针,指向后续的处理请求的对象(如果有的话)。
实现:
//抽象机类,定义一个处理请求的接口 class Handler { public: Handler(Handler* pSuccessor=NULL):m_pSuccessor(pSuccessor){} virtual ~Handler() { delete m_pSuccessor; m_pSuccessor = NULL; } //虚函数,由派生类实现 virtual void HandlerRequest()=0; protected: Handler* m_pSuccessor; }; class ConcreteHandler1:public Handler { public: ConcreteHandler1(Handler* pSuccessor=NULL):Handler(pSuccessor){} virtual ~ConcreteHandler1(){} virtual void HandlerRequest() { if(NULL!=m_pSuccessor) m_pSuccessor->HandlerRequest(); else cout<<"HandlerRequest by ConcreteHandler1"<<endl; } }; class ConcreteHandler2:public Handler { public: ConcreteHandler2(Handler* pSuccessor=NULL):Handler(pSuccessor){} virtual ~ConcreteHandler2(){} virtual void HandlerRequest() { if(NULL!=m_pSuccessor) m_pSuccessor->HandlerRequest(); else cout<<"HandlerRequest by ConcreteHandler2"<<endl; } }; int main() { Handler* p1 = new ConcreteHandler1(); Handler* p2 = new ConcreteHandler2(p1); p2->HandlerRequest(); delete p2; return 0; }
3. Command——对象行为模式
作用:
将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
UML结构图:
解析:
Command模式的思想是把命令封装在一个类中,就是这里的Command基类,同时把接收对象也封装在一个类中即这里的Receiver类,由调用这个命令的类即Invoker类来调用。Command类的作用和面向过程的回调函数类似,采用Command模式解耦了命令的发出者和命令的执行者。
实现:
class Reciever { public: Reciever(){} ~Reciever(){} void Action() { cout<<"Reciever action ..."<<endl; } }; class Command { public: virtual ~Command(){} virtual void Excute()=0; protected: Command(){} }; class ConcreteCommand:public Command { public: ConcreteCommand(Reciever* rev) { this->_rev = rev; } ~ConcreteCommand() {} void Excute() { if(NULL!=_rev) _rev->Action(); cout<<"ConcreteCommand.."<<endl; } private: Reciever* _rev; }; class Invoker { public: Invoker(Command* cmd) { _cmd = cmd; } ~Invoker() { delete _cmd; } void Invoke() { _cmd->Excute(); } private: Command* _cmd; }; int main() { Reciever* rev = new Reciever(); Command* cmd = new ConcreteCommand(rev); Invoker* inv = new Invoker(cmd); inv->Invoke(); delete inv; return 0; }
4. Observer——对象行为型模式
作用:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
UML结构图:
解析:
Observer模式定义的是一对多(一个Subject对多个Observer)关系,当Subject类的状态发生变化的时候通知与之对应的Observer类们也去相应的更新状态,同时支持动态的添加和删除Observer对象的功能。
Observer模式的实现要点是,第一一般Subject类都是采用链表等容器来存放Observer对象,第二抽出Observer对象的而一些公共的属性形成Observer基类,而Subject中保存的则是Observer类对象的指针,这样就使Subject和具体的Observer实现了解耦,即Subject不需要关心具体是哪个Observer放进了自己的容器。
实现:
typedef int STATE; class Subject; //Observer抽象基类 class Observer { public: Observer():m_nObserverState(-1){} virtual ~Observer(){} //纯虚函数,各个派生类可能有不同的实现 //通知Observer状态发生了改变 virtual void Update(Subject* pSubject)=0; protected: STATE m_nObserverState; //模拟保存Observer状态的变量 }; //Subject抽象基类,只需要知道Observer基类的声明就可以了 class Subject { public: Subject():m_nSubjectState(-1){} virtual ~Subject() { list<Observer*>::iterator iter1,iter2,temp; for(iter1=m_ListObserver.begin(),iter2=m_ListObserver.end(); iter1!=iter2;) { temp = iter1; ++iter1; delete (*temp); } m_ListObserver.clear(); } void Notify() //通知对象改变状态 { cout<<"Notify Observer's State"<<endl; list<Observer*>::iterator iter1,iter2; for(iter1=m_ListObserver.begin(),iter2=m_ListObserver.end(); iter1!=iter2;++iter1) (*iter1)->Update(this); } } void Attach(Observer* pObserver) //新增对象 { cout<<"Attach an Observer"<<endl; m_ListObserver.push_back(pObserver); } void Detach(Observer* pObserver) // 删除对象 { list<Observer*>::iterator iter; iter = find(m_ListObserver.begin(),m_ListObserver.end(),pObserver); if(m_ListObserver.end()!=iter) m_ListObserver.erase(iter); cout<<"Detach an Observer"<<endl; } //虚函数,提供默认的实现,派生类可以自己实现来覆盖基类的实现 virtual void SetState(STATE nState) //设置状态 { cout<<"SetState by Subject"<<endl; m_nSubjectState = nState; } virtual STATE GetState() //得到状态 { cout<<"GetState by Subject"<<endl; return m_nSubjectState; } protected: STATE m_nSubjectState; //模拟保存Subject状态的变量 list<Observer*> m_ListObserver; //保存Observer指针的链表 }; //ConcreteSubject类,派生自Subject类 class ConcreteSubject:public Subject { public: ConcreteSubject():Subject(){} virtual ~ConcreteSubject(){} //派生类自己实现来覆盖基类的实现 virtual void SetState(STATE nState) //设置状态 { cout<<"SetState by ConcreteSubject"<<endl; m_nSubjectState = nState; } virtual STATE GetState() //得到状态 { cout<<"GetState by ConcreteSubject"<<endl; return m_nSubjectState; } }; //ConcreteObserver类派生自Observer类 class ConcreteObserver:public Observer { public: ConcreteObserver():Observer(){} virtual ~ConcreteObserver(){} //虚函数,实现基类提供的接口 virtual void Update(Subject* pSubject) { if(NULL==pSubject) return; m_nObserverState = pSubject->GetState(); cout<<"The OberverState is"<<m_nObserverState<<endl; } }; int main() { Observer* p1 = new ConcreteObserver; Observer* p2 = new ConcreteObserver; Subject* p = new ConcreteSubject; p->Attach(p1); p->Attach(p2); p->SetState(4); p->Notify(); p->Detach(p1); p->SetState(10); p->Notify(); delete p; return 0; }
5. Strategy——对象行为型模式
作用:
定义一系列的算法,把他们一个个封装起来,并且使它们可以相互替换。本模式使得算法可独立于使用它的客户而变化。
UML结构图:
解析:
Strategy模式是对算法的封装,处理一个问题的时候可能有多种算法,这些算法的接口(输入参数、输出参数)都是一致的,那么可以考虑采用Strategy模式对这些算法进行封装,在基类中定义一个函数接口即可。
实现:
class Strategy { public: virtual ~Strategy(){} virtual void AlgorithmInterface()=0; }; class ConcreteStrategyA:public Strategy { public: virtual ~ConcreteStrategyA(){} virtual void AlgorithmInterface() { cout<<"AlgorithmInterface Implemented by ConcreteStrategyA"<<endl; } }; class Context { public: Context(Strategy* pStrategy):m_pStrategy(pStrategy){} ~Context() { delete m_pStrategy; m_pStrategy = NULL; } void ContextInterface() { if(NULL!=m_pStrategy) m_pStrategy->AlgorithmInterface(); } private: Strategy* m_pStrategy; }; int main() { Strategy* pStrategy = new ConcreteStrategyA(); Context* pContext = new Context(pStrategy); pContext->ContextInterface(); delete pContext; return 0; }