设计模式 --> (3)策略模式

策略模式

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

优点:

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

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

 

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

//抽象接口  
class WeaponBehavior  
{  
public:  
    virtual void useWeapon() = 0;  
};  
//三种具体的替换算法 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 = 0; }  
    void setWeapon(WeaponBehavior *w) 
   {
     this->weapon = w;
   }
void virtual fight() = 0; 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 0; }

 

方式二

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

//Character需要用到替换算法  
enum WEAPON {WEAPON_AK, WEAPON_KNIFE, WEAPON_RIFLE}; //标签    
class Character  
{  
public:  
    Character() { weapon = 0; }  
    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() = 0; 
    
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 0;  
}

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

 

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

 

posted @ 2015-10-31 13:04  蚂蚁吃大象、  阅读(276)  评论(0编辑  收藏  举报