一、Strategy模式
1. 特点说明:
- 定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。
- 适用场景:
- 许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
- 需要使用一个算法的不同变体。
- 算法使用客户不应该知道的数据。使用策略模式避免暴露复杂的、与算法相关的数据结构。
- 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入他们各自的Strategy类中以代替这些条件语句。
2. 基本的实现代码

/**
* 体操策略模式基类.
*/
class StrategyGym
{
public:
StrategyGym();
virtual ~StrategyGym();
virtual void DoGym() = 0; //纯虚函数
};
//--------体操基类实现--------
StrategyGym::StrategyGym()
{
}
StrategyGym::~StrategyGym()
{
cout << "~StrategyGym....."<<endl;
}
/**
* 眼保健操策略类.
*/
class StrategyEyeGym : public StrategyGym
{
public:
StrategyEyeGym();
virtual ~StrategyEyeGym();
void DoGym();
};
//--------眼保健操类--------
StrategyEyeGym::StrategyEyeGym()
{
}
StrategyEyeGym::~StrategyEyeGym()
{
cout << "打完收工....." << endl;
}
//做啥捏? 眼保健操
void StrategyEyeGym::DoGym()
{
cout << "做眼保健操1->4节." << endl;
}
/**
* 广播体操策略类.
*/
class StrategyBroadcastGym :
public StrategyGym
{
public:
StrategyBroadcastGym();
virtual ~StrategyBroadcastGym();
void DoGym();
};
//--------广播体操--------
StrategyBroadcastGym::StrategyBroadcastGym()
{
}
StrategyBroadcastGym::~StrategyBroadcastGym()
{
cout << "广播体操,做完....." << endl;
}
void StrategyBroadcastGym::DoGym()
{
cout << "做广播体操1->8节." << endl;
}
/**
* 策略使用类
*/
class Context
{
public:
Context(StrategyGym* stg);
~Context();
void DoAction();
private:
StrategyGym* _stg; //体操的基类指针
};
//--------策略使用者.--------
Context::Context(StrategyGym* stg)
{
_stg = stg;
}
Context::~Context()
{
if (_stg != NULL)
{
delete _stg;
}
}
void Context::DoAction()
{
/* 一旦选择一个算法, 就完全切换了整个算法.
一个算法与另外一个算法, 没有什么共同的地方.*/
_stg->DoGym();
}
上述代码类图表示为:

调用者的代码:
//策略模式例子
//眼保健操
StrategyGym* sEye = new StrategyEyeGym();
Context contextEye(sEye);
contextEye.DoAction();
//广播体操
StrategyGym* sBroad = new StrategyBroadcastGym();
Context contestBroad(sBroad);
contestBroad.DoAction();
3. 策略模式浅析:
- 优点
- Strategy类层次定义了一系列的可供重用的算法或行为;
- 消除条件语句;
- Strategy提供相同行为的不同实现;
- 缺点
- 客户必须了解不同的Strategy;
- Strategy和Context之间的通信开销;
- 增加了对象的数目;
二、Template Method模式
1. 特点说明
- 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
- 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
- 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
- 各子类中公共的行为被提取出来并集中到一个公共父类中,避免代码重复。
- 注:Template Method模式和C++模板一点关系都没有
2. 基本代码实现

class TemplateMethod
{
public:
virtual ~TemplateMethod();
void DoGym(); //对外部的接口
protected:
//实际需要调用的虚函数, 需要派生类实现
virtual void Section1st() = 0;
virtual void Section2nd() = 0;
virtual void Section3rd() = 0;
virtual void Section4th() = 0;
virtual void Section5th() = 0;
virtual void Section6th() = 0;
virtual void Section7th() = 0;
virtual void Section8th() = 0;
TemplateMethod();
};
TemplateMethod::TemplateMethod()
{
}
TemplateMethod::~TemplateMethod()
{
}
/* 对外的接口函数, 调用实际的处理函数,
这样, 如果派生类的实现有改动,接口是不需要改动的.
把公共的部分, 放在接口中, 这是外部使用这个算法时, 不变的部分,
比如一个算法的步骤.
*/
void TemplateMethod::DoGym()
{
/* 就目前而言, 不管哪一套广播体操, 一般是8节, 这8节的具体做法可能不一样,就需要派生类具体实现了.但整个广播体操的整体架构是一样的, 都是8节, 都是从第1节做到第8节.*/
Section1st();
Section2nd();
Section3rd();
Section4th();
Section5th();
Section6th();
Section7th();
Section8th();
}
//第8套广播体操
class BroadcastGymEighth : public TemplateMethod
{
public:
BroadcastGymEighth();
~BroadcastGymEighth();
protected:
void Section1st();
void Section2nd();
void Section3rd();
void Section4th();
void Section5th();
void Section6th();
void Section7th();
void Section8th();
};
//第8套广播体操
BroadcastGymEighth::BroadcastGymEighth()
{ }
BroadcastGymEighth::~BroadcastGymEighth()
{}
void BroadcastGymEighth::Section1st()
{
cout << "第八套广播体操, 第1节." << endl;
}
void BroadcastGymEighth::Section2nd()
{
cout << "第八套广播体操, 第2节." << endl;
}
void BroadcastGymEighth::Section3rd()
{
cout << "第八套广播体操, 第3节." << endl;
}
void BroadcastGymEighth::Section4th()
{
cout << "第八套广播体操, 第4节." << endl;
}
void BroadcastGymEighth::Section5th()
{
cout << "第八套广播体操, 第5节." << endl;
}
void BroadcastGymEighth::Section6th()
{
cout << "第八套广播体操, 第6节." << endl;
}
void BroadcastGymEighth::Section7th()
{
cout << "第八套广播体操, 第7节." << endl;
}
void BroadcastGymEighth::Section8th()
{
cout << "第八套广播体操, 第8节." << endl;
}
//第9套广播体操
class BroadcastGymNinth : public TemplateMethod
{
public:
BroadcastGymNinth();
~BroadcastGymNinth();
protected:
void Section1st();
void Section2nd();
void Section3rd();
void Section4th();
void Section5th();
void Section6th();
void Section7th();
void Section8th();
};
//第套广播体操
BroadcastGymNinth::BroadcastGymNinth()
{}
BroadcastGymNinth::~BroadcastGymNinth()
{}
void BroadcastGymNinth::Section1st()
{
cout << "第九套广播体操, 第1节." << endl;
}
void BroadcastGymNinth::Section2nd()
{
cout << "第九套广播体操, 第2节." << endl;
}
void BroadcastGymNinth::Section3rd()
{
cout << "第九套广播体操, 第3节." << endl;
}
void BroadcastGymNinth::Section4th()
{
cout << "第九套广播体操, 第4节." << endl;
}
void BroadcastGymNinth::Section5th()
{
cout << "第九套广播体操, 第5节." << endl;
}
void BroadcastGymNinth::Section6th()
{
cout << "第九套广播体操, 第6节." << endl;
}
void BroadcastGymNinth::Section7th()
{
cout << "第九套广播体操, 第7节." << endl;
}
void BroadcastGymNinth::Section8th()
{
cout << "第九套广播体操, 第8节." << endl;
}
上述代码类图表示如下:

调用者代码:
/* 模板方法模式 */
//第八套广播体操
TemplateMethod* t = new BroadcastGymEighth();
t->DoGym();
delete t;
t = NULL;
//第九套广播体操
t = new BroadcastGymNinth();
t->DoGym();
delete t;
t = NULL;
3. Template Method模式附加说明:
当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现。
我们通过模板方法模式,把这些行为搬移到单一的地方,这样就可以帮助子类摆脱重复的不变行为的纠缠。
三、Strategy模式和Template Method模式的比较:
1. Strategy模式
- 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法的变化可独立于使用它的客户。
- 使用委托来改变整个算法。
2. Template Method模式
- 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
- 使用继承来改变算法的一部分。
|