Behavior.Strategy(行为型模式—策略模式)

策略模式(Strategy Pattern)的定义

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

  ①算法是同一接口的不同实现,地位是平等的,可以相互替换。

  ②引入上下文对象,可以实现让算法能独立使用它的客户。因为这个对象负责持有算法,但不负责决定具体选用哪个算法,把选择算法的功能交给了客户。

  ③当客户通知上下文对象执行功能的时候,上下文会转调具体的算法

(2)策略模式的结构和说明



  ①Strategy:策略接口,用来约束一系列具体的策略算法。Context使用这个接口来调用具体的策略实现定义的算法。

  ②ConcreteStrategy:具体的策略实现,也就是具体的算法实现。

  ③Context:上下文,负责和具体的策略类交互。通常会持有一个真正的策略实现,上下文还可以让具体的策略类来获取上下文的数据,甚至让具体的策略来回调上下文的方法

思考策略模式

(1)策略模式的本质分离算法,选择实现

(2)策略模式的重心:不是如何实现算法,而是如何组织、调用这一系列的算法,从而让程序结构更加灵活,具有更好的维护性和扩展性。

(3)算法的平等性

  策略模式一个很大的特点就是各个策略算法的平等性。对于一系列具体的策略算法大家的地位是完全一样的,所以才能实现算法之间可以相互替换。可以这样描述策略算法:它是相同行为的不同实现。(如同样是打折这一行为,但商家可以在不同的时间,选择不同的打折策略

4)谁来选择具体的策略算法

  ①一个地方是在客户端,当使用上下文的时候,由客户端选择具体的策略算法,然后把这个策略算法设置给上下文。

  ②还有一个地方是由上下文选择具体的策略算法。而状态模式可以由具体的状态实现去切换不同的状态。

(5)Strategy角色的实现方式:可以使用接口或抽象类,特别是当多个算法具有公共功能的时候,可以把Strategy实现成为抽象类。

(6)运行时策略的唯一性:运行期间,策略模式在每一个时刻只能使用一个具体的策略实现对象,虽然可以动态地在不同策略实现中切换,但是同时只能使用一个。

(7)Context和Strategy的关系

  ①在策略模式中,通常是上下文使用具体的策略实现对象。反过来,策略实现对象也可以从上下文获取所需要的数据。因此可以将上下文当作参数传递给策略实现对象。

  ②在这种情况下,上下文封装着具体策略对象进行算法运算所需要的数据,具体策略对象通过回调上下文的方法来获取这些数据。

容错恢复机制

(1)在程序运行的时候,正常情况下应该按照某种方式来做,此时如果发生错误的话,系统并不会崩溃,而是有容忍出错的能力

(2)不但能容忍程序运行出现错误,还提供出现错误后的备用方案,也就是恢复机制来代替正常执行的功能,使程序继续向下运行。如日志记录,一般会记录在数据库里,但是当数据库暂时连不上时,可先记录在文本文件里,然后在合适的时候再转录到数据库中。

【编程实验】日志记录策略

 


//行为型模式——策略模式
//场景:容错恢复机制(策略模式+模板方法)
/*
    将日志记录到数据库和文件
*/
#include <iostream>
#include <string>

using namespace std;

//日志记录策略的接口
class CLogStrategy{
public:
	virtual void WriteLog(string log) = 0;//记录日志
	virtual ~CLogStrategy(){}
};

//实现日志策略接口
//把日志记录到数据库
class CDbLog : public CLogStrategy{
public:
	void WriteLog(string log){
		//制造错误,模仿数据库断开连接
		try{if(log.length() >= 30)		throw -1;}
		catch(...){throw -1;}
		//数据连接正常时,直接写入数据库
		cout << "Write log : \"" << log << "\" into Database." << endl;
	}
};

//把日志记录到文件
class CFileLog : public CLogStrategy{
public:
	void WriteLog(string log){cout << "Write log : \"" << log << "\" into File." << endl;}
};

//日志记录的上下文
class CLogContext{
private:
	CLogStrategy* pStrategy;
public:
	CLogContext(){pStrategy = NULL;}
	~CLogContext(){Clr();}
	void Clr(){
		if(pStrategy != NULL){
			delete pStrategy; pStrategy = NULL;
		}
	}
	void DoLog(string log){
		 //在上下文中,自行实现对具体策略的选择
		try{//优先选用策略:记录到数据库
			Clr();
			pStrategy = new CDbLog();
			pStrategy->WriteLog(log);
		}
		catch(...){//出错了,那就记录到文件中
			Clr();
			pStrategy = new CFileLog();
			pStrategy->WriteLog(log);
		}
		Clr();
	}
};

void StrategyTst()
{
	CLogContext oLogContext;
	oLogContext.DoLog("abcdefghijklmnopqrstuvwxyz");
	oLogContext.DoLog("abcdefghijklmnopqrstuvwxyz1234");
}


猜你喜欢

转载自blog.csdn.net/KnightOnHourse/article/details/80048697