一 使用场景
景区的门票对于学生是五折优惠,对于军人是免费,其他人是无折扣。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。
二 定义
策略模式 Strategy Pattern:定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换,策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。策略模式是一种对象行为型模式。
Context 环境类:环境类是使用算法的角色,它在解决某个问题(即实现某个方法)时可以采用多种策略。在环境类中维持一个对抽象策略类的引用实例,用于定义所采用的策略。
Strategy 抽象策略类:它为所支持的算法声明了抽象方法,是所有策略类的父类,它可以是抽象类或具体类,也可以是接口。环境类通过抽象策略类中声明的方法在运行时调用具体策略类中实现的算法。
ConcreteStrategy 具体策略类:它实现了在抽象策略类中声明的算法,在运行时,具体策略类将覆盖在环境类中定义的抽象策略类对象,使用一种具体的算法实现某个业务处理。
三 C++实现
People.h 相当于Context
#pragma once
#include <string>
#include <iostream>
#include "Strategy.h"
using namespace std;
class People //游客类
{
public:
People(std::string _name){
m_name = _name;
}
virtual ~People(){}
void setDiscount(Strategy * _stra){
m_strategy = _stra;
}
void getDiscount(){ //游客获取的折扣
m_strategy->DisCount(m_name);
}
private:
std::string m_name;
Strategy * m_strategy;
};
Strategy.h
#pragma once
#include <string>
#include <iostream>
using namespace std;
class Strategy //抽象策略
{
public:
Strategy(){}
virtual ~Strategy(){}
virtual void DisCount(std::string _name) = 0;
};
class FiveDiscount:public Strategy // 五折优惠
{
public:
FiveDiscount(){}
virtual ~FiveDiscount(){}
void DisCount(std::string _name){
std::cout << "50% discount for: " << _name << std::endl;
}
};
class Free:public Strategy // 免费
{
public:
Free(){}
virtual ~Free(){};
void DisCount(std::string _name){
std::cout << "free for: " << _name << std::endl;
}
};
class NoDiscount:public Strategy // 没有优惠
{
public:
NoDiscount(){}
virtual ~NoDiscount(){}
void DisCount(std::string _name){
std::cout << "no discount for: " << _name << std::endl;
}
};
main.h
#include <iostream>
#include "People.h"
using namespace std;
int main()
{
People * people = new People("student");
Strategy * strategy = new FiveDiscount();
people->setDiscount(strategy);
people->getDiscount();
strategy = new Free();
people = new People("armyman");
people->setDiscount(strategy);
people->getDiscount();
system("pause");
return 0;
}
运行结果
四 总结
优点:
1 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免代码重复。
2 支持开闭准则,不修改原有算法的基础上可以增加算法。
3 避免较多的判断语句。
缺点:
1 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
2,由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么对象的数目就会很可观。