行为型模式--策略

1、意图

  定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

2、结构

 

 

3、参与者

  Strategy:策略。定义所有支持的算法的公共接口。Context使用这个接口来调用某ConcreteStrategy定义的算法;

  ConcreteStrategy:具体策略。以Strategy接口实现某具体算法。

  Context:上下文。用一个ConcreteStrategy对象来配置;维护一个对Strategy对象的引用;可定义一个接口来让Stategy访问它的数据;

4、适用性

  当存在以下情况时使用策略模式:

  1)许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法;

  2)需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间时间权衡的算法。当这些变体实现为一个算法的类层次时,可以使用策略模式;

  3)算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。

  4)一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移人它们各自的Strategy类中以代替这些条件语句。

5、代码示例

  场景:采用不同算法对一个正文流进行分行

// Composition类负责维护和更新一个正文浏览程序中显示的正文换行。
// Composition类维护一个Component实例的集合,它们代表一个文档中的正文和图形元素。
// Composition使用一个封装了某种分行策略的Compositor子类实例将Component对象编排成行。
// 每一个Component都有相应的正常大小、可伸展性和可收缩性。可伸展性定义了该Component可以增长到超出正常大小的程度;
// 可收缩性定义了它可以收缩的程度。Composition将这些值传递给一个Compositor,它使用这些值来决定换行的最佳位置。

class Composition 
{
public:
    Composition (Compositor*); 
    void Repair(); 
private:
    Compositor* _compositor; 
    Component* _components;// the list of components 
    int _componentCount;   // the number of components 
    int _linewidth;        // the Composition's line width 
    int* _lineBreaks;      // the position of linebreaks in components 
    int lineCount;           // the number of lines
};
// Compositor各个子类实现不同的换行策略:
class Compositor 
{
public:
    virtual int Compose(Coord natural[], Coord stretch[], Coord shrink[], 
        int componentCount, int linewidth, int breaks[])=0; 
protected:
    Compositor ();
};

void Composition::Repair ()
{
    Coord* natural; 
    Coord* stretchability; 
    Coord* shrinkability; 
    int componentCount;
    int* breaks;
    
    // prepare the arrays with the desired component sizes
    // ...
    
    // determine where the breaks are:
    int breakCount; 
    breakCount = _compositor->Compose(natural, stretchability, shrinkability, 
        componentCount, _linewidth, breaks):
    
    // lay out components according to breaks
    // ...
}
// SimpleCompositor实现一个简单的策略,它一次决定一个换行位置。
class simpleCompositor : public Compositor
{
public:
    SimpleCompositor(); 
    virtual int Compose(Coord natural[], Coord stretch[], Coord shrink[], 
        int componentCount, int linewidth, int breaks[]);
    // ...
};

// TeXCompositor实现查找换行位置的TEX算法。这个策略尽量全局地优化换行,也就是一次处理一段文字的换行
class TexCompositor : public Compositor
{
public:
    TexCompositor(); 
    virtual int Compose(Coord natural[], Coord stretch[], Coord shrink[],
        int componentCount, int linewidth, int breaks[]);
    // ...
};

// ArrayCompositor实现一个策略,该策略使得每一行都含有一个固定数目的项。例如,用于对一系列的图标进行分行。
class ArrayCompositor : public Compositor
{
public:
    ArrayCompositor(int interval); 
    virtual int Compose(Coord natural[], Coord stretch[], Coord shrink[],
        int componentCount, int linewidth, int breaks[]);
    // ...
};
// 实例化Composition时需把想要使用的Compositor传递给它:
Composition* quick = new Composition(new simpleCompositor); 
Composition* slick = new Composition(new TeXCompositor);
Composition* iconic = new Composition(new ArrayCompositor(100));

6、总结

  策略模式将同一行为下的不同算法用不同的策略类实现,使得算法可以独立于客户而变化。用户可以根据不同的应用场景需求切换使用不同的算法策略。

posted @ 2022-05-04 18:11  流翎  阅读(44)  评论(0)    收藏  举报