1、意图
Define a family of algorithms, encapsulate each one, and make them interchangeable.Strategy lets the algorithm vary independently from clients that use it.
2、适应性
Use the Strategy pattern
• many related classes differ only in their behavior. Strategiesprovide a way to configure a class with one of many behaviors.
• you need different variants of an algorithm. For example, you might definealgorithms reflecting different space/time trade-offs.Strategies can be used when these variants are implemented as a classhierarchy of algorithms [HO87].
• an algorithm uses data that clients shouldn't know about. Use theStrategy pattern to avoid exposing complex, algorithm-specific datastructures.
• a class defines many behaviors, and these appear as multipleconditional statements in its operations. Instead of manyconditionals, move related conditional branches into their ownStrategy class.
3、结构
4、示例代码
The Composition class maintains a collection ofComponent instances, which represent text and graphicalelements in a document. Note that Compositor is an abstract class. Concretesubclasses define specific linebreaking strategies.
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
};
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
// ...
}
The Compositor interface lets the composition pass thecompositor all the information it needs. This is an example of"taking the data to the strategy":
class Compositor {
public:
virtual int Compose(
Coord natural[], Coord stretch[], Coord shrink[],
int componentCount, int lineWidth, int breaks[]
) = 0;
protected:
Compositor();
};
Now let's look at the Compositor subclasses:
// SimpleCompositor examines components
a line at a time todetermine where breaks should go:
class SimpleCompositor : public Compositor {
public:
SimpleCompositor();
virtual int Compose(
Coord natural[], Coord stretch[], Coord shrink[],
int componentCount, int lineWidth, int breaks[]
);
// ...
};
// TeXCompositor uses a more global strategy. It examines a paragraph at a time, taking
// into account the components' sizeand stretchability.
class TeXCompositor : public Compositor {
public:
TeXCompositor();
virtual int Compose(
Coord natural[], Coord stretch[], Coord shrink[],
int componentCount, int lineWidth, int breaks[]
);
// ...
};
// ArrayCompositor breaks the components into lines at regularintervals.
class ArrayCompositor : public Compositor {
public:
ArrayCompositor(int interval);
virtual int Compose(
Coord natural[], Coord stretch[], Coord shrink[],
int componentCount, int lineWidth, int breaks[]
);
// ...
};
// To instantiate Composition, you pass it the compositoryou want to use:
Composition* quick = new Composition(new SimpleCompositor);
Composition* slick = new Composition(new TeXCompositor);
Composition* iconic = new Composition(new ArrayCompositor(100));