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

  • 相关阅读:
    .NET面试题目
    ASP.NET应用管理系统框架概述(三)
    ASP.NET应用管理系统框架概述(二)
    ASP.NET应用管理系统框架概述(一)
    InstallShield使用文档
    dotnet的安装包例子
    Access数据库连接池
    InstallShield使用——InstallScript MIS Project例子
    InstallShield使用——例子
    ASP.NET针对Sybase数据库使用分页技术
  • 原文地址:https://www.cnblogs.com/jeakeven/p/4925375.html
Copyright © 2020-2023  润新知