[设计模式] 21 策略模式 Strategy

原文链接: http://www.cnblogs.com/diegodu/p/4451343.html

在GOF的《设计模式:可复用面向对象软件的基础》一书中对策略模式是这样说的:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。该模式使得算法可独立于使用它的客户而变化。

策略模式为了适应不同的需求,只把变化点封装了,这个变化点就是实现不同需求的算法,但是,用户需要知道各种算法的具体情况。就像上面的加班工资,不同的加班情况,有不同的算法。我们不能在程序中将计算工资的算法进行硬编码,而是能自由的变化的。这就是策略模式。

Jelly want | an original article sharing site

Strategy:定义所有支持的算法的公共接口。Context使用这个接口来调用某ConcreteStrategy定义的算法;
ConcreteStrategy:实现Strategy接口的具体算法;
Context:使用一个ConcreteStrategy对象来配置;维护一个对Stategy对象的引用,同时,可以定义一个接口来让Stategy访问它的数据。

 

 

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

       什么是Cache的替换算法呢?简单解释一下, 当发生Cache缺失时,Cache控制器必须选择Cache中的一行,并用欲获得的数据来替换它。所采用的选择策略就是Cache的替换算法。下面给出相应的UML图。

       ReplaceAlgorithm is an abstract class that defines the interface algorithms, there are three classes inherit from the abstract class, which is a specific algorithm. Cache class requires replacement algorithm, and therefore maintain the target of a ReplaceAlgorithm. Structure is a typical structure of this strategy pattern UML diagram. The UML diagram below, to give the corresponding implementation.

       Firstly, the definition of replacement algorithms.

//抽象接口
class ReplaceAlgorithm
{
public:
    virtual void Replace() = 0;
};
//三种具体的替换算法
class LRU_ReplaceAlgorithm : public ReplaceAlgorithm
{
public:
    void Replace() { cout<<"Least Recently Used replace algorithm"<<endl; }
};

class FIFO_ReplaceAlgorithm : public ReplaceAlgorithm
{
public:
    void Replace() { cout<<"First in First out replace algorithm"<<endl; }
};
class Random_ReplaceAlgorithm: public ReplaceAlgorithm
{
public:
    void Replace() { cout<<"Random replace algorithm"<<endl; }
};

    Cache then give the definition, it is the key here, Cache implementation of a direct impact on the customer's use, the key is how to specify the replacement algorithm.

         1: Direct parameter specified pointer passed a particular algorithm.

// the Cache Replacement Algorithm need to use 
class the Cache 
{ 
Private : 
    ReplaceAlgorithm * m_ra;
 public : 
    the Cache (ReplaceAlgorithm * RA) = {m_ra RA;}
     ~ the Cache () { Delete m_ra;}
     void the Replace () {m_ra-> the Replace ( );} 
};

If this way, customers need to know the specific definition of these algorithms. Can only be used in this way below, you can see exposed too much detail.

int main () 
{ 
    the Cache Cache ( new new LRU_ReplaceAlgorithm ()); // exposed algorithm defined 
    cache.Replace ();
     return  0 ; 
}

       Second way: through direct parameter is specified, but instead of passing a pointer, but a label. As long as the appropriate tag so that customers can know the algorithm, without the need to know the specific definition of the algorithm.

// the Cache Replacement Algorithm need to use 
enum the RA {the LRU, the FIFO, the RANDOM}; // tag 
class the Cache 
{ 
Private : 
    ReplaceAlgorithm * m_ra;
 public : 
    the Cache ( enum the RA RA) 
    { 
        IF (RA == the LRU) 
            m_ra = new new LRU_ReplaceAlgorithm ();
         the else  IF (RA == the FIFO) 
            m_ra = new new FIFO_ReplaceAlgorithm ();
         the else  IF (RA == the RANDOM) 
            m_ra =new new Random_ReplaceAlgorithm ();
         the else  
            m_ra = NULL; 
    }
     ~ the Cache () { Delete m_ra;}
     void the Replace () {m_ra-> the Replace ();} 
}; 

int main () 
{ 
    ; the Cache Cache (the LRU) // specified tag can 
    cache.Replace ();
     return  0 ; 
}

       Compared a way, this way easy to use them more. In fact, this way a simple factory pattern combined with the Strategy pattern together, define the algorithm uses a strategy pattern, and in fact, the definition of Cache uses a simple factory pattern.

 

          The above two methods, the constructor parameter are required. Whether parameter constructor can not do? A third implementation is given below.

 

          Three ways: using a template to achieve. Algorithm specified by the argument of the template. Of course, still use the argument, but not the constructor arguments. In strategy mode, the transmission parameters is difficult to avoid, customers must specify an algorithm.

// the Cache Replacement Algorithm need to use 
Template < class the RA>
 class the Cache 
{ 
Private : 
    the RA m_ra; 
public : 
    the Cache () {}
     ~ the Cache () {}
     void the Replace () {m_ra.Replace ();} 
}; 

int main () 
{ 
    the Cache <Random_ReplaceAlgorithm> Cache; // template argument 
    cache.Replace ();
     return  0 ; 
}

 

Reproduced in: https: //www.cnblogs.com/diegodu/p/4451343.html

Guess you like

Origin blog.csdn.net/weixin_30892889/article/details/94792004