策略模式

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

优点:

  1、 简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。
  2、 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
  3、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。

缺点:
  1、 因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。
  2、 在基本的策略模式中,选择所用具体实现的职责由客户端对象承担,并转给策略模式的Context对象

以CS里的人物作为例子,每个人都可以有几个武器,武器之间动态切换,武器拥有统一的攻击命令,首先给出替换算法的定义:

//抽象接口
class WeaponBehavior
{
public:
virtual void useWeapon() = ;
};
//三种具体的替换算法
class AK47 : public WeaponBehavior
{
public:
void useWeapon() { cout<< "Use AK47 to shoot!" <<endl; }
}; class Knife : public WeaponBehavior
{
public:
void useWeapon() { cout<< "Use Knife to kill!" <<endl; }
};
class Rifle : public WeaponBehavior
{
public:
void useWeapon() { cout<< "Use Rifle to shoot!" <<endl; }
};

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

方式一

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

//Character需要用到替换算法
class Character
{
public:
Character() { weapon = ; }
void setWeapon(WeaponBehavior *w)
   {
     this->weapon = w;
   }
void virtual fight() = ; protected:
WeaponBehavior *weapon;
}; class King:public Character
{
public:
void fight()
{
if ( this->weapon == NULL)
     {
        cout << "You don't have a weapon! Please Set Weapon!" << endl;
     }
else
     {
       weapon->useWeapon();
     }
}
}; int main()
{
Character *kin = new King();
kin->fight();

WeaponBehavior *ak47 = new AK47();
kin->setWeapon(ak47); //暴露了算法的定义
kin->fight();     if(kin) delete kin;
return ;
}

方式二

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

//Character需要用到替换算法
enum WEAPON {WEAPON_AK, WEAPON_KNIFE, WEAPON_RIFLE}; //标签
class Character
{
public:
Character() { weapon = ; }
void setWeapon(enum WEAPON w)
{
if(w == WEAPON_AK) weapon = new AK47();
else if(w == WEAPON_KNIFE) weapon = new Knife();
else if(w == WEAPON_RIFLE) weapon = new Rifle();
else weapon = NULL;
}
void virtual fight() = ; protected:
WeaponBehavior *weapon;
}; class King:public Character
{
public:
void fight()
{
if ( this->weapon == NULL)
{
cout << "You don't have a weapon! Please Set Weapon!" << endl;
}
else
{
weapon->useWeapon();
}
}
}; int main()
{
Character *kin = new King();
kin->fight(); kin->setWeapon(WEAPON_AK);
kin->fight(); if(kin) delete kin;
return ;
}

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

出处: http://blog.csdn.net/wuzhekai1985

设计模式 --> (3)策略模式的更多相关文章

  1. 设计模式:策略模式(Strategy)

    定   义:它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化, 不会影响到使用算法的客户. 示例:商场收银系统,实现正常收费.满300返100.打8折.......等不同收费 ...

  2. PHP设计模式之策略模式

    前提: 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能.如查 找.排序等,一种常用的方法是硬编码(Hard Cod ...

  3. JavaScript设计模式之策略模式(学习笔记)

    在网上搜索“为什么MVC不是一种设计模式呢?”其中有解答:MVC其实是三个经典设计模式的演变:观察者模式(Observer).策略模式(Strategy).组合模式(Composite).所以我今天选 ...

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

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

  5. JavaScript设计模式之策略模式

    所谓"条条道路通罗马",在现实中,为达到某种目的往往不是只有一种方法.比如挣钱养家:可以做点小生意,可以打分工,甚至还可以是偷.抢.赌等等各种手段.在程序语言设计中,也会遇到这种类 ...

  6. 【设计模式】【应用】使用模板方法设计模式、策略模式 处理DAO中的增删改查

    原文:使用模板方法设计模式.策略模式 处理DAO中的增删改查 关于模板模式和策略模式参考前面的文章. 分析 在dao中,我们经常要做增删改查操作,如果每个对每个业务对象的操作都写一遍,代码量非常庞大. ...

  7. [design-patterns]设计模式之一策略模式

    设计模式 从今天开始开启设计模式专栏,我会系统的分析和总结每一个设计模式以及应用场景.那么首先,什么是设计模式呢,作为一个软件开发人员,程序人人都会写,但是写出一款逻辑清晰,扩展性强,可维护的程序就不 ...

  8. 设计模式入门,策略模式,c++代码实现

    // test01.cpp : Defines the entry point for the console application.////第一章,设计模式入门,策略模式#include &quo ...

  9. 设计模式之策略模式和状态模式(strategy pattern & state pattern)

    本文来讲解一下两个结构比较相似的行为设计模式:策略模式和状态模式.两者单独的理解和学习都是比较直观简单的,但是实际使用的时候却并不好实践,算是易学难用的设计模式吧.这也是把两者放在一起介绍的原因,经过 ...

  10. python设计模式之策略模式

    每次看到项目中存在大量的if else代码时,都会心生一丝不安全感. 特别是产品给的需求需要添加或者更改一种if条件时,生怕会因为自己的疏忽而使代码天崩地裂,哈哈,本文的目的就是来解决这种不安全感的, ...

随机推荐

  1. Windows2003查看远程桌面连接的用户

    要查看通过远程连接windows2003的用户,则打开任务管理器,切换到“用户”选项卡上进行查看.

  2. ip2long的用法

    ip2long:将IPv4的ip地址(以小数点分隔形式)转换为int Description int ip2long ( string ip_address ) 如果ip地址非法,返回FALSE(PH ...

  3. Linux显示inode的信息

    Linux显示inode的信息 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ df -i 文件系统 Inode 已用(I) 可用(I) 已用(I)% 挂载点 ...

  4. CentOS恢复系统启动grub1.5,2阶段

    1.模拟CentOS7系统/boot下文件全丢失 rm -rf  /boot/* 2.重启系统,并进入救援模式 3.将救援光盘路径切换回原来的系统磁盘根路径 chroot /mnt/sysimage ...

  5. IE浏览器兼容的常见问题及解决方案

    常见6个问题及解决方案 1 IE6/IE7对display:inline-block的支持还欠缺 就是我们做导航栏时通常会用到<ul><li>标签去写,在现在一些主流的浏览器中 ...

  6. Mybatis if test 中int判断非空的坑

    Mybatis 中,alarmType 是int类型.如果alarmType 为0的话,条件判断返回结果为false,其它值的话,返回true. <if test="alarmType ...

  7. Python Web-第二周-正则表达式(Using Python to Access Web Data)

    0.课程地址与说明 1.课程地址:https://www.coursera.org/learn/python-network-data/home/welcome 2.课程全名:Using Python ...

  8. JQuery实现点击按钮切换图片(附源码)--JQuery基础

    JQuery实现切换图片相对比较简单,直接贴代码了哈,有注释噢!疑问请追加评论哈,不足之处还请大佬们指出! 1.案例代码: demo.html: <!DOCTYPE html><ht ...

  9. (luogu P1410)子序列 [TPLY]

    子序列 题目链接:https://www.luogu.org/problemnew/show/P1410 吐槽: 这道题做得我心累 本来想好好练一练dp 刷刷水题来练练手感 于是乎打开了(普及+/提高 ...

  10. 【BZOJ3626】LCA(树链剖分,Link-Cut Tree)

    [BZOJ3626]LCA(树链剖分,Link-Cut Tree) 题面 Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1. ...