设计模式(十四)——策略模式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式(十四)——策略模式相关的知识,希望对你有一定的参考价值。

设计模式(十四)——策略模式

一、策略模式简介

1、策略模式简介

    策略模式定义了算法家族,分别封装起来,让不同算法之间可以互相替换,使算法的变化不会影响到使用算法的客户。

    策略模式将算法的逻辑抽象接口(doAction)封装到一个类(Context)里面,通过组合的方式将具体算法的实现在组合对象中实现,再通过委托的方式将抽象接口的实现委托给具体的策略类来实现(ConcreteStrategy)实现

技术分享

    策略模式是一种定义一系列算法的方法,所有算法完成的都是相同的工作,只是实现不同。策略模式可以以相同的方式调用所有的算法,减少了各种算法类使用算法类之间的耦合。
    策略模式就是用来封装算法的,但在实践中,发现可以用策略模式来封装几乎任何类型的规则,只要在分析过程中需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理。
    在基本的策略模式中,选择所用具体实现的职责由客户端对象承担,并转给策略模式的Context对象并没有解除客户端需要选择判断的压力。

2、策略模式角色

 Stragegy策略定义所有支持的算法的公共接口当各个实现类中存在着重复的逻辑时,则使用抽象类来封装公共的代码
       ConcreteStrategy具体策略类:继承于Strategy封装了具体的算法或行为,

 Context上下文:用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用

    策略模式是对算法的封装,把一系列的算法分别封装到对应的类中,并且这些类实现相同的接口,相互之间可以替换。策略模式中,调用算法的主体封装了封装类Context中,抽象策略Strategy一般是一个接口,目的只是为了定义规范,而在实际编程中,因为各个具体策略实现类之间难免存在一些相同的逻辑,为了避免重复的代码,常常使用抽象类来担任Strategy的角色,在里面封装公共的代码

3、策略模式优缺点

策略模式的优点:

    A策略类之间可以自由切换,由于策略类实现自同一个抽象,所以策略类之间可以自由切换。

    B易于扩展,增加一个新的策略对策略模式来说非常容易,基本上可以在不改变原有代码的基础上进行扩展。

    C避免使用多重条件,如果不使用策略模式,对于所有的算法,必须使用条件语句进行连接,通过条件判断来决定使用哪一种算法

策略模式的缺点:

    A维护各个策略类会给开发带来额外开销

    B客户端必须知道所有的策略类,并自行决定使用哪一个策略类

4、策略模式使用场景

策略模式使用场景:

    A需要使用一个算法的不同变体

    B有几种相似的行为,客户端需要动态地决定使用哪一种,可以使用策略模式。

二、策略模式实现

Context封装类:

#ifndef CONTEXT_H

#define CONTEXT_H

#include "Strategy.h"

 

//封装类

class Context

{

public:

    Context(Strategy* strategy)

    {

         m_strategy = strategy;

    }

    void doAction()

    {

        m_strategy->AlgrithmInterface();

    }

private:

    Strategy* m_strategy;

};

 

#endif // CONTEXT_H

Strategy抽象策略类:

#ifndef STRATEGY_H

#define STRATEGY_H

#include <iostream>

 

//抽象策略类

class Strategy

{

public:

    virtual void AlgrithmInterface() = 0;

protected:

    Strategy(){}//不对外开放接口

};

 

#endif // STRATEGY_H

ConcreteStrategyA具体策略类:

#ifndef CONCRETESTRATEGYA_H

#define CONCRETESTRATEGYA_H

#include "Strategy.h"

 

//具体策略类

class ConcreteStrategyA : public Strategy

{

public:

    ConcreteStrategyA(){}

    void AlgrithmInterface()

    {

        std::cout << "ConcreteStrategyA::AlgrithmInterface()" << std::endl;

    }

};

 

#endif // CONCRETESTRATEGYA_H

ConcreteStrategyB具体策略类:

#ifndef CONCRETESTRATEGYB_H

#define CONCRETESTRATEGYB_H

#include "Strategy.h"

 

//具体策略类

class ConcreteStrategyB : public Strategy

{

public:

    ConcreteStrategyB(){}

    virtual void AlgrithmInterface()

    {

        std::cout << "ConcreteStrategyB::AlgrithmInterface()" << std::endl;

    }

};

 

#endif // CONCRETESTRATEGYB_H

客户调用程序:

#include "Strategy.h"

#include "ConcreteStrategyA.h"

#include "ConcreteStrategyB.h"

#include "Context.h"

 

int main()

{

    Strategy* pStrategy = new ConcreteStrategyA();

    Context* pContext = new Context(pStrategy);

    pContext->doAction();

    delete pStrategy;

    delete pContext;

 

    pStrategy = new ConcreteStrategyB();

    pContext = new Context(pStrategy);

    pContext->doAction();

 

    delete pStrategy;

    delete pContext;

    return 0;

}

三、策略模式实例

    高速缓存(Cache)替换算法,当发生Cache缺失时,Cache控制器必须选择Cache中的一行,并用欲获得的数据来替换。所采用的选择策略就是Cache的替换算法。

策略模式的UML图如下:

技术分享

        ReplaceAlgorithm是一个抽象类,定义了算法的接口。Cache类中需要使用替换算法,因此维护了一个 ReplaceAlgorithm的对象。

Cache封装类:

#ifndef CACHE_H

#define CACHE_H

#include "ReplaceAlgorithm.h"

#include "FIFO_ReplaceAlgorithm.h"

#include "LRU_ReplaceAlgorithm.h"

#include "Random_ReplaceAlgorithm.h"

 

 

//Cache替换算法

enum RA {LRU, FIFO, RANDOM}; //标签

class Cache

{

public:

    Cache(enum RA ra)

    {

        if(ra == LRU)

            m_replaceAlgorithm = new LRU_ReplaceAlgorithm();

        else if(ra == FIFO)

            m_replaceAlgorithm = new FIFO_ReplaceAlgorithm();

        else if(ra == RANDOM)

            m_replaceAlgorithm = new Random_ReplaceAlgorithm();

        else

            m_replaceAlgorithm = NULL;

    }

    ~Cache()

    {

        delete m_replaceAlgorithm;

    }

    void replace()

    {

        m_replaceAlgorithm->replace();

    }

private:

    ReplaceAlgorithm *m_replaceAlgorithm;

};

 

#endif // CACHE_H

 

ReplaceAlgorithm抽象策略类:

#ifndef REPLACEALGORITHM_H

#define REPLACEALGORITHM_H

#include <iostream>

using namespace std;

 

class ReplaceAlgorithm

{

public:

    virtual void replace() = 0;

protected:

    ReplaceAlgorithm(){}

};

 

#endif // REPLACEALGORITHM_H

 

FIFO_ReplaceAlgorithm具体策略类:

#ifndef FIFO_REPLACEALGORITHM_H

#define FIFO_REPLACEALGORITHM_H

#include "ReplaceAlgorithm.h"

 

class FIFO_ReplaceAlgorithm : public ReplaceAlgorithm

{

public:

    void replace()

    {

        cout << "FIFO_ReplaceAlgorithm::replace" << endl;

    }

};

 

#endif // FIFO_REPLACEALGORITHM_H

LRU_ReplaceAlgorithm具体策略类:

#ifndef LRU_REPLACEALGORITHM_H

#define LRU_REPLACEALGORITHM_H

#include "ReplaceAlgorithm.h"

 

class LRU_ReplaceAlgorithm : public ReplaceAlgorithm

{

public:

    void replace()

    {

        cout << "LRU_ReplaceAlgorithm::replace" << endl;

    }

};

 

#endif // LRU_REPLACEALGORITHM_H

Random_ReplaceAlgorithm具体策略类:

#ifndef RANDOM_REPLACEALGORITHM_H

#define RANDOM_REPLACEALGORITHM_H

#include "ReplaceAlgorithm.h"

 

class Random_ReplaceAlgorithm : public ReplaceAlgorithm

{

public:

    void replace()

    {

        cout << "Random_ReplaceAlgorithm::replace" << endl;

    }

};

 

#endif // RANDOM_REPLACEALGORITHM_H

 

客户调用程序

#include "Cache.h"

 

int main()

{

    Cache cache(LRU); //指定标签即可

    cache.replace();

    return 0;

}

 

        Cache封装类在构造函数中使用简单工厂方法,用算法标签指定调用的具体算法策略类,客户端不需要知道具体的算法策略类。


本文出自 “生命不息,奋斗不止” 博客,谢绝转载!

以上是关于设计模式(十四)——策略模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式十四—— 状态模式/策略模式

二十四种设计模式:策略模式(Strategy Pattern)

JAVA多线程(十四)模式-Active Object

设计模式—策略模式

设计模式---策略模式

策略模式(Strategy Pattern)