页数:30页文件大小:371.7 KB来源: 设计模式ppt课件
本课件接续行为型设计模式,先从类型判断的困境推出访问者模式的双分派实现,再讲模板方法、职责链与命令模式的意图与代码,最后按行为差异、通知访问与交互复杂三类作小结。
2.5访问者模式(Visitor Pattern)
2.5.1例子class Animal {};class Cat:public Animal{public:virtual void Sleep( );};class Dog:public Animal{public:virtual void Eat();virtual void Run();};void main() {Vector<Animal * >*animals = newVector<Animal *>;animals->Add(new Cat);animals->Add(new Dog);Animal * an;for each(an in animals) {if (dynamic_cast<Cat *> (an)!=0) {((Cat*)an)->Sleep( );} else if (dynamic_cast<Dog *>(an)!=0) {((Dog*)an)->Eat();}}问题:
修改Animal及子类classAnimal{public:virtual void Do();};class Cat:public Animal{public:virtual void Do( ) {Sleep();}virtualvoid Sleep();};class Dog:public Animal{public:virtual void Do(){ Eat(); }virtual void Eat();};class Animal {};class Cat:public Animal{public:virtual void Sleep( );};class Dog:public Animal{public:virtual void Eat();virtual void Run();};for each(an in animals) {if (dynamic_cast<Cat *> (an)!=0) {((Cat*)an)->Sleep( );} else if (dynamic_cast<Dog *> (an)!=0) {((Dog*)an)->Eat();}}for each(an in animals) {an->Do( );}
分离稳定与变化部分
变化:操作(Sleep,Eat,Run,…)结构部分(不变,这里简写)class Animal {};class Cat:public Animal{};class Dog:public Animal{};操作部分:(3个不同实现)SleepForCatEatForDogRunForDog如何分组?按Cat、Dog类型分?还是按功能分?按猫狗的类型对操作分组classOperate {public:virtualvoid Sleep();virtualvoid Eat();virtualvoid Run();};class CatOperate:publicOperate {public:virtualvoid Sleep(){}virtualvoid Eat(){}virtualvoid Run(){}};classDogOperate:publicOperate {public:virtualvoid Sleep(){}virtualvoid Eat(){ }virtualvoid Run(){ /* Run() ;* / }};则main中的改为:for each(an in animals) {//创建具体Operate,//需要先确定an是Cat?Dog?operate->Sleep();operate->Eat();}这样不行。还得先确定an的具体类型,才能确定执行的Sleep是哪个类的。按功能对操作分组1)class Visitor {public:virtualvoidVisitCat(Cat *){ }virtualvoidVisitDog(Dog *){ }};class SleepVisitor:publicVisitor {public:virtualvoidVisitCat(Cat* cat){ cat->Sleep();}};class EatVisitor:publicVisitor {public:virtualvoidVisitDog(Dog * dog){ dog->Eat();}};class RunVisitor:publicVisitor {public:virtualvoidVisitDog(Dog * dog){ dog->Run();}};for each(an in animals) {if (dynamic_cast<Cat *> (an)!=0) {((Cat*)an)->Sleep( );} else if (dynamic_cast<Dog *> (an)!=0) {((Dog*)an)->Eat( );}}按功能对操作分组2)SleepVisitor * v1= new SleepVisitor;EatVisitor * v2= new EatVisitor;for each(an in animals) {DoSome(v1,an);DoSome (v2,an ) ;或v1->VisitCat(an);//????v2->VisitDog(an);//?????//还不知道an是Cat,还是Dog呢!!}
class Animal {public:virtual void Accept(Visitor * v);//....};class Cat:public Animal {public:virtual void Accept(Visitor * v){v->VisitCat(this); }//....};class Dog:public Animal {public:virtual void Accept(Visitor * v){v->VisitDog(this); }//....};按功能对操作分组3)修改Animal,添加Accept()SleepVisitor * v1= newSleepVisitor;EatVisitor * v2= new EatVisitor;for each(an in animals) {an->Accept(v1);an->Accept(v2);}for each(an in animals) {if (dynamic_cast<Cat *> (an)!=0){((Cat*)an)->Sleep( );} else if (dynamic_cast<Dog *>(an)!=0) {((Dog*)an)->Eat( );}}2.5.2访问者模式适用性
2.5.3访问者模式使用方法1.分离结构和操作。2.将操作按功能分类(而不是按结构分类)3.按功能定义Visitor类及子类4.在结构Element中添加Accept。5.对Element对象,执行操作。
按功能定义Visitor类及子类classFunc1Visitor:publicVisitor {public:virutal void VisitElementA(ElementA * a){a->doFunc1( );}virutal void VisitElementB(ElementB * b ){b->doFunc1( );}virutal void VisitElementC(ElementC * c){c->doFunc1( );}};classFunc2Visitor:publicVisitor {public:virutal void VisitElementA(ElementA * a){a->doFunc2( );}virutal void VisitElementB(ElementB * b){b->doFunc2( );}virutal void VisitElementC(ElementC * c){c->doFunc2( );}};publicVisitor{public:virutal voidVisitElementA(ElementA * a)=0;virutal voidVisitElementB(ElementB * b )=0;virutal voidVisitElementC(ElementC * c)=0;};classBaseElement {public:virtual void Accept(Visitor * v) = 0;//…..};classElementA:public BaseElement {public:virtual void Accept(Visitor * v){v->VisitElementA(this); }//.....};classElementB:public BaseElement {public:virtual void Accept(Visitor * v){v->VisitElementB(this); }//.....};在结构Element中添加Accept()需执行操作Func1时,可Visitor * v= new Func1Visitor;elem->Accept(v);
2.5.4访问者模式结构
2.6模板方法模式(Template Method Pattern)
2.6.1例子class ProcessFile{public:void Process() {OpenFile();DoFile();CloseFile();}protected:virtual void DoFile() { }virtual void OpenFile() { }virtual void CloseFile() {}};class MyProcessFile:publicProcessFileprotected:virtual void OpenFile(){//......}virtual void DoFile() {//......}};2.6.2模板方法模式适用
2.7职责链模式(Chain of Responsibility)
2.7.1例子class HelpHandler {public:HelpHandler(HelpHandler * next): handler(next){ }virtual void HandleHelp(){ handler->HandleHelp(); }protected:HelpHandler *handler;};class Widget:public HewlpHandler {public:Widget(HelpHandler * next):HelpHandler(next) {}virtual void HandleHelp( ) {if (canHandle) {//Handle Code} else {handler->HandleHelp();}}};class Button:publicWidget{public:Button(HelpHandler * next):Widget(next) {}virtual void HandleHelp( ) {if (canHandle) {//Handle Code} else if (handler) {handler->HandleHelp();}};void main() {Button * btn = new Button(NULL);Window * win = new Window(btn);win->HandleHelp();delete win;delete btn;}2.7.2责任链结构
2.8命令模式(Command Pattern)
2.8.1例class Receiver {};class ReceiverA:public Receiver {};class ReceiverB:public Receiver {};class ReceiverC:public Receiver {};class ReceiverD:public ReceiverC {};class Requester{public:virtual void DoAction1(ReceiverA * a);virtualvoidDoAction1(ReceiverB * b);virtualvoidDoAction2(ReceiverD * d);};问题:1)增加新的ReceiverA2,怎么办?2)同时增加新的RecieverD2,又怎么办?3)增加一个新的Action,它是由DoAction1(ReceiverA * a)和DoAction1(ReceiverB * b)顺序组成的,又怎么办?4)需要对每个Action,都做日志记录,怎么办?5)需要对每个Action,都可以做撤销操作,怎么办?将Requester的DoAction及参数变化单独封装起来:class Requester{public:virtual void DoAction(Command * comd){comd->Excute( );}};class CommandAction2:public Command{public:CommandAction2(ReceiverC *rec):receiver(rec) {}virtual void Excute(){receiver->DoSomething2( ); }private:ReceiverC*receiver;};由Command区分Action及Receiver:class Command {public:virtual void Excute() = 0;};class CommandAction1:public Command{public:CommandAction1(Reciveiver * rec):receiver(rec){ }virtual void Excute(){receiver->DoSomething1(); }private:Receiver*receiver;};队列(例如由两个Command组成的请求队列)class MacroCommod:public Command{public:MacroCommand(Command* comand1,Command* command2):cmd1(command1),cmd2(command2)virtual void Excute( ){cmd1->Excute();cmd2->Excute()}private:Command* cmd1;Command* cmd2;};2.8.3命令模式优缺点好处:
2.8.4命令模式结构
2.9小结
下载地址:{{downurl}}
{{{a}}}
{{#b}}{{{b}}}
{{/b}} {{/title}} {{#nolog}}登陆注册
{{/nolog}} {{#djsx}}点我刷新
{{/djsx}} {{#gocz}} {{/gocz}} {{#ffqr}} {{/ffqr}}