zoukankan      html  css  js  c++  java
  • Head First 设计模式 C++实现-Strategy(策略模式)

     转贴地址:http://blog.csdn.net/NE_Team/archive/2008/07/21/2685689.aspx

    模式定义:定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

    个人见解:基本上所有的模式都是在体现oo的一个设计原则,弱关联(其中之一)。

    书上介绍了一个例子,是关于鸭子的,总体的问题是过多的运用了继承,使整个设计过于紧密,类之间是存在强关联,在软件后期开发弊端凸显。不过这个例子可能和模式本身定义关联不是太大,所以自己想了以下这个例子,用以说明策略模式。

    案例:一个公司,准备做一套计算器, 需要一套软件设计,按照一般的oo设计者来说,可能会用到以下的设计思路DUck

    计算器基类Calculator提供两个方法,Addition()和Subtract(),对于这个设计,初期看不出什么好与不好的,因为它确实能够工作,那么它会在什么时候出现问题呢,

    随着业务的深入,这个时候发现,有新的计算器要来了,那么按照这位设计师的想法,开始从基类派生出来一个Calculator_Three,然后实现两个函数,新的计算器出来了。

    这个时候的Addition和Subtract重写过的,一个问题出在这里,每产生一个新的计算器,我们就要重写这两个方法,毕竟有些计算器方法还是一样的,有人会说,如果有方法一样的计算器,那么我们就让他们保持is-a关系,让一个继承于另外一个,这样虽然能够解决问题,但是这样让人感觉好像就是让猫继承于狗一样别扭。另外一个问题,如果计算器1号突然心血来潮,说自己要用计算器2的Addition方法了,该怎么办?去把2的代码拷贝过来?

    另外这样的设计更多的问题会凸显在算法方面,突然有一天,他们突然开始做一些小型的电脑了,电脑只是比他们先进一点,但是如果要说加减这些算法,大多数都是一样的,这个时候难道把他们的代码一段一段的拷贝过去,去适应新的程序?

    看看上面的一系列问题,想想整个事情错在什么地方,答案:对于程序变化的部分欠考虑。

    对于过早的将算法或者实现绑定到类的设计过后,使得整个程序出现了一种强关联的形式,导致后面的开发陷入一个泥潭,无法或者很难继续,并且对于这钟需要重复利用的算法来说,这样的设计无疑就是要让后期开发在不断的拷贝代码之间进行,并且你要保证你没拷贝错,那应该怎么解决问题呢。

    这个时候就应该策略模式登场了,好好分析以下策略模式的定义,我们会好好想下这个计算器,它应该是这样:动态决定算法类型,算法与实际对象相分离,算法可以用作它用,计算器可以方便的具备其它功能或者说是算法。

    开始OO设计之旅:

    首先重新定义这个计算器基类如下:

    DUck

    这里定义了两个行为类,一个是加法,一个是减法,而计算器基类仍然有以前的两个接口,不过现在多了一些东西,他包含了两个行为类的指针,基类的Addition实现和以前不同的是,现在这个实现是通过m_pAddtionBehavior这个指针来调用加法行为类中的Addition,这是一种组合的方法,C++代码如下

    //加法类
    class AdditionBehavior
    {
    public:
        virtual void Addition();
    };

    //减法类
    class SubtractBehavior
    {
    public:
        virtual void Subtract();
    };

    //计算器类
    class Calculator 
    {
    public:
        Calculator();
        virtual ~Calculator();
    public:
        virtual void Addition()
        {
            m_pAdditionBehavior->Addition();
        }
        virtual void Subtract();
        {
            m_pSubtractBehavior->Subtract();
        }

        virtual void SetAdditionBehavior(AdditionBehavior* pBehavior)
        {
            m_pAdditionBehavior = pBehavior;
        }
        virtual void SetSubtractBehavior(SubtractBehavior* pBehavior)
        {
            m_pSubtractBehavior = pBehavior;
        }


    private:
        AdditionBehavior* m_pAdditionBehavior;
        SubtractBehavior* m_pSubtractBehavior;
    };

    //加法派生类

    class AddtionBehavior_One : public AdditionBehavior
    {
    public:
        virtual void Addition();
    };

    ///////////////////////////////////////////////////////////////////////////////////////////////////

    SetAdditionBehavior是为了让计算器可以在运行时动态的替换算法,上面的代码可以在计算器的构造函数参数里面加个限定,必须要两个行为类的指针作为参数,不过这样好像又是一个强关联了,这个就看自己程序了,如果不加参数,在调用两个指针的方法时候需要检查指针有效性,

    下面讲到了算法复用

    class Computer
    {
    public:
        virtual void Addition()
        {
            m_pAdditionBehavior->Addition();
        }
        virtual void Subtract();
        {
            m_pSubtractBehavior->Subtract();
        }
        virtual void SetAdditionBehavior(AdditionBehavior* pBehavior)
        {
            m_pAdditionBehavior = pBehavior;
        }
        virtual void SetSubtractBehavior(SubtractBehavior* pBehavior)
        {
            m_pSubtractBehavior = pBehavior;
        }
    private:
        AdditionBehavior* m_pAdditionBehavior;
        SubtractBehavior* m_pSubtractBehavior;
    };

    一个新的类型,简单电脑,同样也可以用这些加减法了。只要你希望,你可以让这个电脑或者计算器之间的任何方法重用。

    上面代码的测试如下

    cout << "I'm calculator" << endl;

    //计算器
    Calculator* pCalculator = new Calculator;
    pCalculator->SetAdditionBehavior(new AdditionBehavior);
    pCalculator->Addition();

    pCalculator->SetAdditionBehavior(new AddtionBehavior_One);
    pCalculator->Addition();

    cout << endl;
    cout << "I'm computer" << endl;

    //简单电脑
    Computer* pComputer = new Computer;
    pComputer->SetAdditionBehavior(new AdditionBehavior);
    pComputer->Addition();

    结果:

    I'm calculator
    AdditionBehavior
    AddtionBehavior_One

    I'm computer
    AdditionBehavior

    书上写了一句很好的话  多用组合,少用继承 针对接口编程

  • 相关阅读:
    EntityFramework之领域驱动设计实践
    Entity Framework 学习初级篇1EF基本概况(入门)
    整理一下Entity Framework的查询
    Unity(六):使用场景Ⅲ:用于依赖注入(上)
    比较NHibernate和Entity Framework
    contentclass对应的一些值
    IE8访问架设在Windows Server 2008(R2)的SharePoint Server 2007是验证框问题
    创建一个图文并茂的调查
    SharePoint回环检查(Loopback Check)相关问题
    Something you need to know about Content Deployment in SharePoint
  • 原文地址:https://www.cnblogs.com/zhangyunlin/p/6167973.html
Copyright © 2011-2022 走看看