• 设计模式 --> (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

  • 相关阅读:
    SPOJ SAMER08A
    SPOJ TRAFFICN
    CS Academy Set Subtraction
    CS Academy Bad Triplet
    CF Round 432 C. Five Dimensional Points
    CF Round 432 B. Arpa and an exam about geometry
    SPOJ INVCNT
    CS Academy Palindromic Tree
    身体训练
    简单瞎搞题
  • 原文地址:https://www.cnblogs.com/jeakeven/p/4925375.html
Copyright © 2020-2023  润新知