在GOF的《设计模式:可复用面向对象软件的基础》一书中对策略模式是这样说的:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。该模式使得算法可独立于使用它的客户而变化。

策略模式为了适应不同的需求,只把变化点封装了,这个变化点就是实现不同需求的算法,但是,用户需要知道各种算法的具体情况。就像上面的加班工资,不同的加班情况,有不同的算法。我们不能在程序中将计算工资的算法进行硬编码,而是能自由的变化的。这就是策略模式。

Strategy:定义所有支持的算法的公共接口。Context使用这个接口来调用某ConcreteStrategy定义的算法;
ConcreteStrategy:实现Strategy接口的具体算法;
Context:使用一个ConcreteStrategy对象来配置;维护一个对Stategy对象的引用,同时,可以定义一个接口来让Stategy访问它的数据。

策略模式是指定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。也就是说这些算法所完成的功能一样,对外的接口一样,只是各自实现上存在差异。用策略模式来封装算法,效果比较好。下面以高速缓存(Cache)的替换算法为例,实现策略模式。

什么是Cache的替换算法呢?简单解释一下, 当发生Cache缺失时,Cache控制器必须选择Cache中的一行,并用欲获得的数据来替换它。所采用的选择策略就是Cache的替换算法。下面给出相应的UML图。

ReplaceAlgorithm是一个抽象类,定义了算法的接口,有三个类继承自这个抽象类,也就是具体的算法实现。Cache类中需要使用替换算法,因此维护了一个  ReplaceAlgorithm的对象。这个UML图的结构就是策略模式的典型结构。下面根据UML图,给出相应的实现。

首先给出替换算法的定义。

//抽象接口
class ReplaceAlgorithm
{
public:
virtual void Replace() = ;
};
//三种具体的替换算法
class LRU_ReplaceAlgorithm : public ReplaceAlgorithm
{
public:
void Replace() { cout<<"Least Recently Used replace algorithm"<<endl; }
}; class FIFO_ReplaceAlgorithm : public ReplaceAlgorithm
{
public:
void Replace() { cout<<"First in First out replace algorithm"<<endl; }
};
class Random_ReplaceAlgorithm: public ReplaceAlgorithm
{
public:
void Replace() { cout<<"Random replace algorithm"<<endl; }
};

接着给出Cache的定义,这里很关键,Cache的实现方式直接影响了客户的使用方式,其关键在于如何指定替换算法。

方式一:直接通过参数指定,传入一个特定算法的指针。

//Cache需要用到替换算法
class Cache
{
private:
ReplaceAlgorithm *m_ra;
public:
Cache(ReplaceAlgorithm *ra) { m_ra = ra; }
~Cache() { delete m_ra; }
void Replace() { m_ra->Replace(); }
};

如果用这种方式,客户就需要知道这些算法的具体定义。只能以下面这种方式使用,可以看到暴露了太多的细节。

int main()
{
Cache cache(new LRU_ReplaceAlgorithm()); //暴露了算法的定义
cache.Replace();
return ;
}

方式二:也是直接通过参数指定,只不过不是传入指针,而是一个标签。这样客户只要知道算法的相应标签即可,而不需要知道算法的具体定义。

//Cache需要用到替换算法
enum RA {LRU, FIFO, RANDOM}; //标签
class Cache
{
private:
ReplaceAlgorithm *m_ra;
public:
Cache(enum RA ra)
{
if(ra == LRU)
m_ra = new LRU_ReplaceAlgorithm();
else if(ra == FIFO)
m_ra = new FIFO_ReplaceAlgorithm();
else if(ra == RANDOM)
m_ra = new Random_ReplaceAlgorithm();
else
m_ra = NULL;
}
~Cache() { delete m_ra; }
void Replace() { m_ra->Replace(); }
}; int main()
{
Cache cache(LRU); //指定标签即可
cache.Replace();
return ;
}

相比方式一,这种方式用起来方便多了。其实这种方式将简单工厂模式与策略模式结合在一起,算法的定义使用了策略模式,而Cache的定义其实使用了简单工厂模式。

上面两种方式,构造函数都需要形参。构造函数是否可以不用参数呢?下面给出第三种实现方式。

方式三:利用模板实现。算法通过模板的实参指定。当然了,还是使用了参数,只不过不是构造函数的参数。在策略模式中,参数的传递难以避免,客户必须指定某种算法。

//Cache需要用到替换算法
template <class RA>
class Cache
{
private:
RA m_ra;
public:
Cache() { }
~Cache() { }
void Replace() { m_ra.Replace(); }
}; int main()
{
Cache<Random_ReplaceAlgorithm> cache; //模板实参
cache.Replace();
return ;
}

[设计模式] 21 策略模式 Strategy的更多相关文章

  1. 乐在其中设计模式(C#) - 策略模式(Strategy Pattern)

    原文:乐在其中设计模式(C#) - 策略模式(Strategy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 策略模式(Strategy Pattern) 作者:webabc ...

  2. 反馈法学习设计模式(一)——策略模式Strategy Pattern

    简介(Introduction) 之前学习Java8实战时,遇到一个很好的策略模式示例.便想着借着这个示例结合反馈式的方法来,学习策略设计模式,也以便后面反复琢磨学习. 首先我们通过练习,逐步写出符合 ...

  3. JAVA设计模式之策略模式 - Strategy

    在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改.这种类型的设计模式属于行为型模式. 在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 ...

  4. 8.6 GOF设计模式四: 策略模式… Strategy Pattern

    策略模式… Strategy Pattern  在POS系统中,有时需要实行价格优惠, 该如何处理?  对普通客户或新客户报全价  对老客户统一折扣5%  对大客户统一折扣10%  注:课件 ...

  5. 二十四种设计模式:策略模式(Strategy Pattern)

    策略模式(Strategy Pattern) 介绍定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换.本模式使得算法的变化可独立于使用它的客户. 示例有一个Message实体类,对它的操作有 ...

  6. 大熊君说说JS与设计模式之------策略模式Strategy

    一,总体概要 1,笔者浅谈 策略模式,又叫算法簇模式,就是定义了不同的算法,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户. 策略模式和工厂模式有一定的类似,策略模式相对简单容易理解,并 ...

  7. 设计模式之策略模式Strategy

    /** * 策略设计模式 * 策略模式:定义一系列的算法族,使他们之间可以相互转换,动态的改变其行为. * 问题:设计一个鸭子模拟游戏. * 现在有一群鸭子: * ①这些鸭可以有飞的行为(分为快和慢) ...

  8. 大话设计模式之策略模式(strategy)

    策略模式:它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响使用算法的用户. 针对商城收银模式,打折,返现促销等的例子: 打折还是促销其实都是一些算法,可以用工厂模式来 ...

  9. 设计模式 笔记 策略模式 Strategy

    //---------------------------15/04/28---------------------------- //Strategy 策略模式----对象行为型模式 /* 1:意图 ...

随机推荐

  1. 济南学习 Day 3 T3 pm

    仙人掌(cactus)Time Limit:1000ms Memory Limit:64MB题目描述LYK 在冲刺清华集训(THUSC) !于是它开始研究仙人掌,它想来和你一起分享它最近研究的结果. ...

  2. DataGrid3

    a标签,DataGrid的数据绑定 1.function aa(id, url) {            //alert(id);            window.open(url + '&am ...

  3. Windows Phone 7 ListBox 列表项渐显加载动画学习笔记

    在wp7程序中,当程序功能越来越复杂时,性能问题是我们不得不考虑的一个问题.在聊天列表中,如果聊天项过多,而且项目UI组件足够复杂时, 我们不得不想尽办法让UI尽快加载.所以有一种可行的方案,就是像Q ...

  4. Git的学习总结和使用时遇到的问题。

                        git 是一款非常强大的版本控制工具,现在市场占有率应该是一家独大了,以前用svn的童鞋估计都转投git阵营了吧   加上很多公司也用git管理自己的项目,所以 ...

  5. C#操作Excel基本操作

    /// using Microsoft.Office.Core; using Microsoft.Office.Interop.Excel; using System.IO; using System ...

  6. 【Qt】Qt Assistant介绍【转】

    简介 Qt Assistant也就是我们常说的Qt助手,是一款用于呈现在线文档的工具. 简介 一分钟学会使用 Qt参考文档 Qt Assistant详解 命令行选项 工具窗口 文档窗口 工具栏 菜单 ...

  7. 如何通过jquery隐藏和显示元素

    以下几种方式可以隐藏一个元素:1,CSS display的值是none.2,type="hidden"的表单元素.3,宽度和高度都显式设置为0.4,一个祖先元素是隐藏的,该元素是不 ...

  8. phpExcel导出excel的类,每步都有说明

    require_once WEB_PATH . '/lib/PHPExcel/PHPExcel.php'; require_once WEB_PATH . '/lib/PHPExcel/PHPExce ...

  9. Android关于buildToolVersion与CompileSdkVersion的区别

    StackOverFlow中对这个问题进行了详细的讨论:http://stackoverflow.com/questions/24521017/android-gradle-buildtoolsver ...

  10. 精美舒适的对话消息提示框--第三方开源--SweetAlertDialog

    SweetAlertDialog(sweet-alert-dialog)是一个套制作精美.动画效果出色生动的Android对话.消息提示框 SweetAlertDialog(sweet-alert-d ...