本文共 1832 字,大约阅读时间需要 6 分钟。
1. 意图 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。 2. 动机 有许多算法可对一个正文流进行分行。将这些算法硬编进使用它们的类中是不可取的,其原因如下: • 需要换行功能的客户程序如果直接包含换行算法代码的话将会变得复杂,这使得客户程序庞大并且难以维护, 尤其当其需要支持多种换行算法时问题会更加严重。 • 不同的时候需要不同的算法,我们不想支持我们并不使用的换行算法。 • 当换行功能是客户程序的一个难以分割的成分时,增加新的换行算法或改变现有算法将十分困难。我们可以定义一些类来封装不同的换行算法,从而避免这些问题。一个以这种方法封装的算法称为一个策略( s t r a t e g y ),如下图所示。
假设一个C o m p o s i t i o n类负责维护和更新一个正文浏览程序中显示的正文换行。换行策略不是C o m p o s i t i o n 类实现的,而是由抽象的C o m p o s i t o r类的子类各自独立地实现的。C o m p o s i t o r各个子类实现不同的换行策略: • S i m p l e C o m p o s i t o r实现一个简单的策略,它一次决定一个换行位置。 • Te X C o m p o s i t o r实现查找换行位置的T E X算法。这个策略尽量全局地优化换行,也就是,一次处理一段文字的换行。 • ArrayCompositor实现一个策略, 该策略使得每一行都含有一个固定数目的项。例如, 用于对一系列的图标进行分行。 C o m p o s i t i o n维护对C o m p o s i t o r对象的一个引用。一旦C o m p o s i t i o n重新格式化它的正文,它就将这个职责转发给它的C o m p o s i t o r对象。C o m p o s i t i o n的客户指定应该使用哪一种C o m p o s i t o r的方式是直接将它想要的C o m p o s i t o r装入C o m p o s i t i o n中。
3.结构
• S t r a t e g y(策略,如C o m p o s i t o r ) — 定义所有支持的算法的公共接口。C o n t e x t使用这个接口来调用某C o n c r e t e S t r a t e g y定 义的算法。 • C o n c r e t e S t r a t e g y(具体策略,如S i m p l e C o m p o s i t o r, Te X C o m p o s i t o r, ArrayCompositor) — 以S t r a t e g y接口实现某具体算法。 • C o n t e x t(上下文,如C o m p o s i t i o n ) — 用一个C o n c r e t e S t r a t e g y对象来配置。 — 维护一个对S t r a t e g y对象的引用。 — 可定义一个接口来让S t a t e g y访问它的数据。
4.举例
#ifndef STRATEGY_H#define STRATEGY_H#includeusing std::cout;using std::endl;class Weapon{public: virtual void fight()=0;};class AK47 : public Weapon{public: virtual void fight(){ cout<<"Use the AK47 to shoot!"< fight(); }};#endif#include "strategy.h"int main(){ Soldier Ruin; Ruin.Action(); Weapon* pWeaponA=new AK47; Weapon* pWeaponB=new Knife; Ruin.SetWeapon(pWeaponA); Ruin.Action(); Ruin.SetWeapon(pWeaponB); Ruin.Action(); delete pWeaponA; delete pWeaponB; return 0;}