Published on

设计模式(21)——策略 Strategy

Authors
  • avatar
    Name
    Leon
    Twitter

二十一、Strategy(策略模式,别名 Policy 政策,对象行为型模式)

1. 意图:

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

2. 适用:

  1. 许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
  2. 需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/时间权衡的算法。当这些变体实现为一个算法的类层次时,可以使用策略模式。
  3. 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
  4. 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的 Strategy 类中以代替这些条件语句。

3. 类图:

4. 应用:

  系统使用不同的迭代器(正序迭代器,反序迭代器,中序迭代器)可以认为就是策略模式的一个实例。不同迭代器的使用接口和方式完全一样,当系统想要切换遍历容器的方式时,只要创建一个相应的迭代器,而使用迭代器的方式完全不用改变。

5. 中间层思考:

  策略模式抽象出了一个 Strategy 类作为中间层,系统不直接访问某一个具体的算法,而是通过访问 Strategy 抽象类来调用算法,这样可以动态地在运行时切换算法。

6. C++实现:

  1. 编写策略抽象基类 Strategy,含有一个纯虚函数提供算法实现的接口 virtual void AlgrithmInterface() = 0;,具体子类如 ConcreteStrategyAConcreteStrategyB 实现不同的算法行为。
  2. 编写环境类 Contexthas-a 组合一个 Strategy 对象 _stg,含有一个执行函数 DoAction(),函数体内调用 _stg 的算法接口 AlgrithmInterface()

Strategy.h

//Strategy.h
#pragma once

class Strategy {
public:
	Strategy();
	virtual ~Strategy();
	virtual void AlgrithmInterface() = 0;
protected:
private:
};

class ConcreteStrategyA : public Strategy {
public:
	ConcreteStrategyA();
	virtual ~ConcreteStrategyA();
	void AlgrithmInterface();
protected:
private:
};

class ConcreteStrategyB : public Strategy {
public:
	ConcreteStrategyB();
	virtual ~ConcreteStrategyB();
	void AlgrithmInterface();
protected:
private:
};

Strategy.cpp

//Strategy.cpp
#include "Strategy.h"
#include <iostream>
using namespace::std;

Strategy::Strategy() {}
Strategy::~Strategy() {
	cout << "~Strategy......" << endl;
}
void Strategy::AlgrithmInterface(){}

ConcreteStrategyA::ConcreteStrategyA() {}
ConcreteStrategyA::~ConcreteStrategyA(){
	cout << "~ConcreteStrategyA......" << endl;
}
void ConcreteStrategyA::AlgrithmInterface() {
	cout << "test ConcreteStrategyA......" << endl;
}

ConcreteStrategyB::ConcreteStrategyB() {}
ConcreteStrategyB::~ConcreteStrategyB() {
	cout << "~ConcreteStrategyB......" << endl;
}
void ConcreteStrategyB::AlgrithmInterface() {
	cout << "test ConcreteStrategyB......" << endl;
}

Context.h

//Context.h
#pragma once

class Strategy;

/*
	这个类是 Strategy 模式的关键,也是 Strategy 模式和 Template 模式的根本区别所在。
	Strategy 通过“组合”(委托)方式实现算法(实现)的异构,而 Template 模式则采取的是继承方式。
	这两个模式的区别也是继承和组合两种实现接口征用的方式的区别。
*/

class Context {
public:
	Context(Strategy* stg);
	~Context();
	void DoAction();
protected:
private:
	Strategy* _stg;
};

Context.cpp

//Context.cpp

#include "Context.h"
#include "Strategy.h"

#include <iostream>
using namespace::std;

Context::Context(Strategy* stg) {
	_stg = stg;
}
Context::~Context() {
	if (!_stg)
		delete _stg;
}
void Context::DoAction() {
	_stg->AlgrithmInterface();
}

main.cpp

//main.cpp

#include "Context.h"
#include "Strategy.h"
#include <iostream>
using namespace::std;

int main(int argc, char* argv[]) {
	Strategy* stg = new ConcreteStrategyA();
	Context* con = new Context(stg);
	con->DoAction();
	if (NULL != con)
		delete con;
	return 0;
}