本文共 3732 字,大约阅读时间需要 12 分钟。
目录
策略模式定义了一系列的算法,并将每个算法封装成一个对象,使得对象之间可以相互替换。这种模式使得算法与使用它的客户分离开来,算法可以独立地进行变化。
Strategy(策略):定义所有支持的算法的公共接口。Context使用这个接口来调用某ConcreteStrategy定义的算法。
ConcreteStrategy(具体策略):以Strategy接口实现某具体算法。
Context(上下文):用一个ConcreteStrategy对象来配置;维护一个对Strategy对象的引用;可定义一个接口来让Strategy访问它的数据。
这里的关键就是将算法的逻辑抽象接口(ContextInterface)封装到一个类中(Context), 再通过委托的方式将具体的算法实现委托给具体的Strategy类来实现(ConcreteStrategyA,B,C类)。
#includeusing namespace std;class Strategy{public: Strategy(){} virtual ~Strategy() {} virtual void AlgorithmInterface() = 0;};class ConcreteStrategyA:public Strategy{public: ConcreteStrategyA() {} virtual ~ConcreteStrategyA() { cout<<"ConcreteStrategyA::Destructor"< AlgorithmInterface(); }private: Strategy* _stg;};int main(){ Strategy *pStg = new ConcreteStrategyA; Context *pCtx = new Context(pStg); pCtx->ContextInterface(); if(NULL!=pCtx) delete pCtx; pStg = new ConcreteStrategyB; pCtx = new Context(pStg); pCtx->ContextInterface(); if(NULL!=pCtx) delete pCtx; system("pause"); return 0;}
运行结果为:
ConcreteStrategyA::AlgorithmInterface ConcreteStrategyA::Destructor ConcreteStrategyB::AlgorithmInterface ConcreteStrategyB::Destructor Strategy模式的代码很直观,关键是将算法的逻辑封装到一个类中。#includeusing namespace std;//排序行为class SortBehavior{public: virtual void sort() const = 0;};//归并排序class Merge:public SortBehavior{public: virtual void sort() const { cout<<"Merge sort()"< sort(); } void search() const { _search->search(); }};int main(int argc, char *argv[]){ Merge merge; Quick quick; Heap heap; Sequential sqn; BinaryTree bt; HashTable ht; Context ctx; ctx.set_sort(&merge); ctx.sort(); ctx.set_search(&bt); ctx.search(); system("pause"); return 0;}
运行结果为:
Merge sort() BinaryTree search() 基于以上结果,可以得到下面的总结: 1).存在两个接口: SortBehavior以及SearchBehavior,连同实现了每个具体行为的相关的类。 2).依靠这种设计,其他类型的对象可以重用这里的搜索以及排序行为,因为这些行为不再被隐藏于我们的聚合类中。 3).并且,无需修改已存在行为类的任何数据,就可以添加新的行为进来。 4).定义了下面的对象指针,它们在运行时期间指向特定的行为类。 class Context { private: SortBehavior *_sort; SearchBehavior *_search; } 5).依靠这些对象指针,我们可以实现每种行为 void sort() const { _sort->sort(); } void search() const { _search->search(); } 6).Context对象不会自己去处理排序行为,而是将此行为委托给对象指针_sort去处理。 7).我们无需关心Context对象类型是什么,只需关心它是否知道如何去排序(如何调用sort()函数)。 8).实际上,上面代码中我们也使用了组合来提供更多的灵活性。它不仅使得我们可以把算法系列封装在它们自己各自的类中,还可以让我们在运行时期间改变行为,只要组合的这个对象实现了正确的行为接口(例如,_sort实现了sort(), _search实现了search())。在这个例子中,有两种方法来记录联系人信息:stream & database. 对应的两个类(StreamRecord以及DatabaseRecord),通过基类函数store(),共享了相同的接口。
class Record{public: virtual void start_record() = 0; virtual void store_field(const string &name, const string &value) = 0; virtual void finish_record() = 0; virtual ~Record() {}};struct ContactData{ string first_name, last_name, phone, email;};class ContactRecorder{public: ContactRecorder(Record *a) : _record(a) { assert(NULL!=a); } void store(const ContactData &data) { assert(NULL!=_record); _record->start_record(); _record->store_field("first name", data.first_name); _record->store_field("last name", data.last_name); _record->store_field("phone", data.phone); _record->store_field("email", data.email); _record->finish_record(); }private: Record *_record;};class StreamRecorder:public Record{public: StreamRecorder(ostream &s, const string &record_name=string()):_ostream(s), \ _record_name(record_name) { } void start_record() { _ostream<<_record_name<<"("; } void store_field(const string &name, const string &value) { _ostream<<<": "< <<"; "; } void finish_record() { _ostream<<") "<
运行结果为:
(first name: Phill; last name: Collyns; phone: 123-456-789; email: pc@email.com; ) start tranaction insert into table insert into table insert into table insert into table finish transaction转载地址:http://aleji.baihongyu.com/