设计模式(十四)——策略模式
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式(十四)——策略模式相关的知识,希望对你有一定的参考价值。
设计模式(十四)——策略模式
一、策略模式简介
1、策略模式简介
策略模式定义了算法家族,分别封装起来,让不同算法之间可以互相替换,使算法的变化不会影响到使用算法的客户。
策略模式将算法的逻辑抽象接口(doAction)封装到一个类(Context)里面,通过组合的方式将具体算法的实现在组合对象中实现,再通过委托的方式将抽象接口的实现委托给具体的策略类来实现(ConcreteStrategy)实现。
策略模式是一种定义一系列算法的方法,所有的算法完成的都是相同的工作,只是实现不同。策略模式可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。
策略模式就是用来封装算法的,但在实践中,发现可以用策略模式来封装几乎任何类型的规则,只要在分析过程中需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理。
在基本的策略模式中,选择所用具体实现的职责由客户端对象承担,并转给策略模式的Context对象,并没有解除客户端需要选择判断的压力。
2、策略模式角色
Stragegy策略类:定义所有支持的算法的公共接口,当各个实现类中存在着重复的逻辑时,则使用抽象类来封装公共的代码。
ConcreteStrategy具体策略类:继承于Strategy,封装了具体的算法或行为,
Context上下文:用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用
策略模式是对算法的封装,把一系列的算法分别封装到对应的类中,并且这些类实现相同的接口,相互之间可以替换。策略模式中,调用算法的主体封装在了封装类Context中,抽象策略Strategy一般是一个接口,目的只是为了定义规范,而在实际编程中,因为各个具体策略实现类之间难免存在一些相同的逻辑,为了避免重复的代码,常常使用抽象类来担任Strategy的角色,在里面封装公共的代码。
3、策略模式优缺点
策略模式的优点:
A、策略类之间可以自由切换,由于策略类实现自同一个抽象,所以策略类之间可以自由切换。
B、易于扩展,增加一个新的策略对策略模式来说非常容易,基本上可以在不改变原有代码的基础上进行扩展。
C、避免使用多重条件,如果不使用策略模式,对于所有的算法,必须使用条件语句进行连接,通过条件判断来决定使用哪一种算法
策略模式的缺点:
A、维护各个策略类会给开发带来额外开销
B、客户端必须知道所有的策略类,并自行决定使用哪一个策略类
4、策略模式使用场景
策略模式使用场景:
A、需要使用一个算法的不同变体
B、有几种相似的行为,客户端需要动态地决定使用哪一种,可以使用策略模式。
二、策略模式实现
Context封装类:
#ifndef CONTEXT_H
#define CONTEXT_H
#include "Strategy.h"
//封装类
class Context
{
public:
Context(Strategy* strategy)
{
m_strategy = strategy;
}
void doAction()
{
m_strategy->AlgrithmInterface();
}
private:
Strategy* m_strategy;
};
#endif // CONTEXT_H
Strategy抽象策略类:
#ifndef STRATEGY_H
#define STRATEGY_H
#include <iostream>
//抽象策略类
class Strategy
{
public:
virtual void AlgrithmInterface() = 0;
protected:
Strategy(){}//不对外开放接口
};
#endif // STRATEGY_H
ConcreteStrategyA具体策略类:
#ifndef CONCRETESTRATEGYA_H
#define CONCRETESTRATEGYA_H
#include "Strategy.h"
//具体策略类
class ConcreteStrategyA : public Strategy
{
public:
ConcreteStrategyA(){}
void AlgrithmInterface()
{
std::cout << "ConcreteStrategyA::AlgrithmInterface()" << std::endl;
}
};
#endif // CONCRETESTRATEGYA_H
ConcreteStrategyB具体策略类:
#ifndef CONCRETESTRATEGYB_H
#define CONCRETESTRATEGYB_H
#include "Strategy.h"
//具体策略类
class ConcreteStrategyB : public Strategy
{
public:
ConcreteStrategyB(){}
virtual void AlgrithmInterface()
{
std::cout << "ConcreteStrategyB::AlgrithmInterface()" << std::endl;
}
};
#endif // CONCRETESTRATEGYB_H
客户调用程序:
#include "Strategy.h"
#include "ConcreteStrategyA.h"
#include "ConcreteStrategyB.h"
#include "Context.h"
int main()
{
Strategy* pStrategy = new ConcreteStrategyA();
Context* pContext = new Context(pStrategy);
pContext->doAction();
delete pStrategy;
delete pContext;
pStrategy = new ConcreteStrategyB();
pContext = new Context(pStrategy);
pContext->doAction();
delete pStrategy;
delete pContext;
return 0;
}
三、策略模式实例
高速缓存(Cache)替换算法,当发生Cache缺失时,Cache控制器必须选择Cache中的一行,并用欲获得的数据来替换。所采用的选择策略就是Cache的替换算法。
策略模式的UML图如下:
ReplaceAlgorithm是一个抽象类,定义了算法的接口。Cache类中需要使用替换算法,因此维护了一个 ReplaceAlgorithm的对象。
Cache封装类:
#ifndef CACHE_H
#define CACHE_H
#include "ReplaceAlgorithm.h"
#include "FIFO_ReplaceAlgorithm.h"
#include "LRU_ReplaceAlgorithm.h"
#include "Random_ReplaceAlgorithm.h"
//Cache替换算法
enum RA {LRU, FIFO, RANDOM}; //标签
class Cache
{
public:
Cache(enum RA ra)
{
if(ra == LRU)
m_replaceAlgorithm = new LRU_ReplaceAlgorithm();
else if(ra == FIFO)
m_replaceAlgorithm = new FIFO_ReplaceAlgorithm();
else if(ra == RANDOM)
m_replaceAlgorithm = new Random_ReplaceAlgorithm();
else
m_replaceAlgorithm = NULL;
}
~Cache()
{
delete m_replaceAlgorithm;
}
void replace()
{
m_replaceAlgorithm->replace();
}
private:
ReplaceAlgorithm *m_replaceAlgorithm;
};
#endif // CACHE_H
ReplaceAlgorithm抽象策略类:
#ifndef REPLACEALGORITHM_H
#define REPLACEALGORITHM_H
#include <iostream>
using namespace std;
class ReplaceAlgorithm
{
public:
virtual void replace() = 0;
protected:
ReplaceAlgorithm(){}
};
#endif // REPLACEALGORITHM_H
FIFO_ReplaceAlgorithm具体策略类:
#ifndef FIFO_REPLACEALGORITHM_H
#define FIFO_REPLACEALGORITHM_H
#include "ReplaceAlgorithm.h"
class FIFO_ReplaceAlgorithm : public ReplaceAlgorithm
{
public:
void replace()
{
cout << "FIFO_ReplaceAlgorithm::replace" << endl;
}
};
#endif // FIFO_REPLACEALGORITHM_H
LRU_ReplaceAlgorithm具体策略类:
#ifndef LRU_REPLACEALGORITHM_H
#define LRU_REPLACEALGORITHM_H
#include "ReplaceAlgorithm.h"
class LRU_ReplaceAlgorithm : public ReplaceAlgorithm
{
public:
void replace()
{
cout << "LRU_ReplaceAlgorithm::replace" << endl;
}
};
#endif // LRU_REPLACEALGORITHM_H
Random_ReplaceAlgorithm具体策略类:
#ifndef RANDOM_REPLACEALGORITHM_H
#define RANDOM_REPLACEALGORITHM_H
#include "ReplaceAlgorithm.h"
class Random_ReplaceAlgorithm : public ReplaceAlgorithm
{
public:
void replace()
{
cout << "Random_ReplaceAlgorithm::replace" << endl;
}
};
#endif // RANDOM_REPLACEALGORITHM_H
客户调用程序
#include "Cache.h"
int main()
{
Cache cache(LRU); //指定标签即可
cache.replace();
return 0;
}
Cache封装类在构造函数中使用简单工厂方法,用算法标签指定调用的具体算法策略类,客户端不需要知道具体的算法策略类。
本文出自 “生命不息,奋斗不止” 博客,谢绝转载!
以上是关于设计模式(十四)——策略模式的主要内容,如果未能解决你的问题,请参考以下文章