【设计模式】状态模式、责任链模式、迭代器模式、解释器模式

1、状态模式

简介

事物在不同的状态下会产生不同的动作,也会从一个状态转换到另一个状态。

当状态数目不多时可以用switch/case解决,但是当状态数目很多时维护很大一组switch/case将变得困难。

将状态逻辑和动作实现分离,而不是直接将状态的代码写在动作逻辑中,以便更好的进行扩展和维护。

优点:

  • 封装了转换规则。
  • 枚举可能的状态,在枚举状态之前需要确定状态种类。
  • 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
  • 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
  • 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

角色

  • 一个抽象的状态类,提供统一的接口
  • 若干个具体的状态,根据自己代表的状态重写父类的接口,拥有一个活动类的指针
  • 一个活动类,拥有所有的具体状态的指针,和一个当前状态的指针,拥有和状态类对应的操作接口,在调用操作接口时调用当前状态的操作接口

代码实现

模拟机器状态变化的过程。假设一个机器有三种状态,分别是正常、出错、维修中,我定义了这三种状态,活动类中有一个m_count计数器,假设这是机器的可靠指数,每次运行时消耗可靠指数,当可靠指数小于0时进入出错状态,出错状态不能运行,需要进行维修,然后进入维修状态,在维修状态运行时会再次出错,需要再次维修,则可靠指数加2,进入正常状态。

#include<iostream>
using namespace std;

class State{
public:
	virtual void ErrorHappened()=0;
	virtual bool Fix()=0;
	virtual bool Run()=0;
	virtual void show()=0;
};

class Activity;

class Normal : public State{
public:
	Normal(Activity * activity);
	void ErrorHappened();
	bool Fix();
	bool Run();
	void show();
private:
	Activity *m_activity;
};

class Error:public State{
public:	
	Error(Activity * activity);
	void ErrorHappened();
	bool Fix();
	bool Run();
	void show();

private:
	Activity *m_activity;
};

class Fixing:public State{
public:
	Fixing(Activity * activity);
	void ErrorHappened();
	bool Fix();
	bool Run();
	void show();
private:
	Activity *m_activity;
};


class Activity{
public:
	State* getState() const{
		return m_state;
	}
	void SetState(State* const state){
		m_state=state;
	}
	int getCount(){
		return m_count--;
	}
	void setCount(const int count){
		m_count=count;
	}
	State* getNormal() const{
		return m_normal;
	}
	void setNormal(State* const normal){
		m_normal=normal;
	}
	State* getError() const{
		return m_error;
	}
	void setError(State* const error){
		m_error=error;
	}
	State* getFixing()const{
		return m_fixing; 
	}
	Activity(int count){
		m_count=count;
		m_error=new Error(this);
		m_normal=new Normal(this);
		m_fixing=new Fixing(this);
		m_state=getNormal();

	}
	void ErrorHappened(){
		m_state->ErrorHappened();
	}
	void Fix(){
		m_count+=2;
		m_state->Fix();
	}
	void Run(){
		if(m_count>0)
			m_count--;
		if(m_count<=0){
			cout<<"Low avialibality "<<endl;
			m_state->ErrorHappened();
			return;
		}
		m_state->Run();

	}
	void show(){
		m_state->show();
	}
private:
	State* m_state;
	int m_count;
	State* m_error;
	State* m_fixing;
	State* m_normal;
};

Normal::Normal(Activity * activity){
	m_activity=activity;
}
void Normal::ErrorHappened(){
	m_activity->SetState(m_activity->getError());
}
bool Normal::Fix(){
	cout<<"No need to fix"<<endl;
	return false;
}
bool Normal::Run(){
	cout<<"Run successfully"<<endl;
	return true;
}
void Normal::show(){
	cout<<"Normal"<<endl;
}

Error::Error(Activity * activity){
	m_activity=activity;
}
void Error::ErrorHappened(){
	cout<<"Already Error"<<endl;
}
bool Error::Fix(){
	m_activity->SetState(m_activity->getFixing());
	return true;
}
bool Error::Run(){
	cout<<"Can't run"<<endl;
	return false;
}
void Error::show(){
	cout<<"Error"<<endl;
}

Fixing::Fixing(Activity* activity){
	m_activity=activity;
}
void Fixing::ErrorHappened(){
	m_activity->SetState(m_activity->getError());
}
bool Fixing::Fix(){
	m_activity->SetState(m_activity->getNormal());
	return true;
}
bool Fixing::Run(){
	cout<<"Can't run"<<endl;
	return false;
}
void Fixing::show(){
	cout<<"Fixing"<<endl;
}


int main(){
	Activity* ac=new Activity(1);
	for(int i=0;;i++){
		 cout<<"time: "<<i<<" state:";
		 ac->show();
		 cout<<endl;
		 cout<<"Input 1.Run   2.Fix  "<<endl;
		 int j=0;
		 cin>>j;
		 if(j==1){
		 	ac->Run();
		 }else if(j==2){
		 	ac->Fix();
		 }else{
		 	cout<<"Wrong operation"<<endl;
		 }

	}
	return 0;
}




2、责任链模式

简介

责任链模式为请求创建了一个接收者对象的链。每个接受者都含有另一个接收者的引用,如果一个接收者不能处理他的请求,就会把这个请求发送给他的下一个接受者了,以此类推。

客户只需要将请求发送到责任链上就可以了,不必关心请求处理的细节和请求的传递过程,实现了请求的发送者和请求的处理者解耦。

优点:

  • 将请求和处理分开,实现解耦,提高系统的灵活性
  • 简化了对象,使对象不需要知道链的结构
  • 调试不方便。采用了类似递归的方式,调试时逻辑可能比较复杂
  • 最佳应用场景:有多个对象可以处理同一个请求时,比如:多级请求、请假/加薪等审批流程、Java Web中Tomcat对Encoding的处理、拦截器

请添加图片描述

角色

  • 一个请求类,包含了请求的各种信息
  • 一个抽象的请求接收者类,拥有一个其他接收者的引用,一个处理请求的接口
  • 若干个不同类型的具体的请求接收者类,重写处理请求的接口

代码实现

模拟公司采购审批的过程。先定义一个采购请求类,包含了采购的金额,再定义一系列有顺序的审批员R1R2R3R4,按照各自的审批金额限制处理采购请求,如前一个不能审批,则传递给下一个审批员。

#include<iostream>
using namespace std;

class Purchase{
public:
	int getType()const{
		return type;
	}
	float getPrice()const{
		return price;
	}
	int getId()const{
		return id;
	}
	Purchase(const int type,const float price,const int id):
	type(type),price(price),id(id){}
private:
	int type;
	float price=0.f;
	int id=0;
};

class Approver{
public:
	void setApprover(Approver* approval){
		this->approval=approval;
	}
	explicit Approver(const string& name):name(name){
	}
	virtual void processRequest(Purchase* purchase)=0;
	string name;
	Approver* approval;
};

class R1:public Approver{
public:
	explicit R1(const string name):Approver(name){}
	void processRequest(Purchase* purchase){
		if(purchase->getPrice()<=5000){
			cout<<"id: "<<purchase->getId()<<
			" are dealed by "<<this->name<<" rank R1"<<endl;
		}else{
			approval->processRequest(purchase);
		}
	}
};

class R2:public Approver{
public:
	explicit R2(const string name):Approver(name){}
	void processRequest(Purchase* purchase){
		if(purchase->getPrice()>5000&&purchase->getPrice()<10000){
			cout<<"id: "<<purchase->getId()<<
			" are dealed by "<<this->name<<" rank R2"<<endl;
		}else{
			approval->processRequest(purchase);
		}
	}
};

class R3:public Approver{
public:
	explicit R3(const string name):Approver(name){}
	void processRequest(Purchase* purchase){
		if(purchase->getPrice()<=10000&&purchase->getPrice()<50000){
			cout<<"id: "<<purchase->getId()<<
			" are dealed by "<<this->name<<" rank R3"<<endl;
		}else{
			approval->processRequest(purchase);
		}
	}
};

class R4:public Approver{
public:
	explicit R4(const string name):Approver(name){}
	void processRequest(Purchase* purchase){
		
		cout<<"id: "<<purchase->getId()<<
		" are dealed by "<<this->name<<" rank R4"<<endl;
		
	}
};

int main(){
	Purchase * p=new Purchase(1,100000,1);
	Approver* r1=new R1("jack");
	Approver* r2=new R2("bob");
	Approver* r3=new R3("dask");
	Approver* r4=new R4("ammb");
	r1->setApprover(r2);
	r2->setApprover(r3);
	r3->setApprover(r4);
	r1->processRequest(p);
	return 0;

}



3、迭代器模式

简介

迭代器模式提供一种遍历集合中所有对象的统一的方式,不需要知道集合对象的底层表示,即不暴露其内部结构。

角色

  • 一个抽象的迭代器类,提供返回第一个、返回下一个、返回当前元素、是否遍历完毕等接口。
  • 一个具体的迭代器类,拥有一个某种数据结构的指针和该数据结构的元素个数。
  • 一个抽象的数据结构类,声明了增加、删除元素、创建迭代器、返回数量等接口。
  • 一个具体的数据结构类,封装原始的数据结构,拥有一个对应的迭代器指针。

代码实现

介绍同上,在需要遍历数据结构的元素时使用该封装过的数据结构里的迭代器进行遍历。

#include<iostream>
#include<string>
#include<vector>

using namespace std;

class Iterator{
public:
	Iterator(){}
	virtual ~Iterator(){}
	virtual string First()=0;
	virtual string Next()=0;
	virtual string Current()=0;
	virtual bool IsDone()=0;
};

class Aggregate{
public:
	virtual int Count()=0;
	virtual void Push(const string& strValue)=0;
	virtual string Pop(const int nIndex)=0;
	virtual Iterator* CreateIterator()=0;
};

class ConcreteIterator:public Iterator{
public:
	ConcreteIterator(Aggregate* paggregate):m_Aggregate(paggregate),m_nCurrent(0),Iterator(){
		
	}
	string First(){
		return m_Aggregate->Pop(0);
	}
	string Next(){
		string strret;
		m_nCurrent++;
		if(m_nCurrent<m_Aggregate->Count()){
			strret=m_Aggregate->Pop(m_nCurrent);
		}
		return strret;
	}
	string Current(){
		return m_Aggregate->Pop(m_nCurrent);
	}

	bool IsDone(){
		return ((m_nCurrent>=m_Aggregate->Count())?true:false);
	}

private:
	Aggregate* m_Aggregate;
	int m_nCurrent;
};

class ConcreteAggregate:public Aggregate{
public:
	ConcreteAggregate():m_pIterator(NULL){
		m_vecItem.clear();
	}
	~ConcreteAggregate(){
		if(m_pIterator !=NULL){
			delete m_pIterator;
			m_pIterator = NULL;
		}
	}
	Iterator* CreateIterator(){
		if(m_pIterator ==NULL){
			m_pIterator=new ConcreteIterator(this);
		}
		return m_pIterator;
	}
	int Count(){
		return m_vecItem.size();
	}
	void Push(const string& strval){
		m_vecItem.push_back(strval);
	}
	string Pop(const int nIndex){
		string strret="";
		if(nIndex<Count()){
			strret=m_vecItem[nIndex];
		}
		return strret;
	}
private:
	vector<string> m_vecItem;
	Iterator* m_pIterator;
};

int main(){
	ConcreteAggregate *pName=NULL;
	pName=new ConcreteAggregate();
	if(pName!=NULL){
		pName->Push("hello");
		pName->Push("world");
		pName->Push("good");
	}
	Iterator* iter=NULL;
	iter=pName->CreateIterator();
	if(iter!=NULL){
		string stritem=iter->First();
		while(!iter->IsDone()){
			cout<<iter->Current()<<endl;
			iter->Next();
		}
	}
	return 0;
}

4、解释器模式

介绍

解释器模式是指给定一个语言(表达式),定义它的文法的一种表示,并定义一个解释器,使用该解释器来解释语言中的句子(表达式)。

应用场景:
1、应用可以将一个需要解释执行的语言中的句子表示为一个抽象语法树
2、一些重复出现的问题可以用一种简单的语言来表达
3、一个简单语法需要解释的场景
4、这样的例子还有,比如编译器、运算表达式计算、正则表达式、机器人等。

优点:

可扩展性比较好,灵活。
增加了新的解释表达式的方式。
易于实现简单文法。

缺点:

可利用场景比较少。
对于复杂的文法比较难维护。
解释器模式会引起类膨胀。
解释器模式采用递归调用方法。

角色

  • 一个封装内容的类,拥有一份未解释的内容和一份解释过的内容,以及对它们的获取和设置操作。
  • 一个抽象的表达式的类,声明一个对内容进行解释的功能。
  • 若干个不同的具体的表达式类,每种具体的表达式类都代表一种解释方法,重写相对应的解释操作。

代码实现

模拟加密解密过程。内容类中包含一个原始数字和一个解释后的数字,两种解释操作分别是将原始数字加一和将原始数字减一(假设这分别代表加密和解密)。

#include<iostream>
#include<string>

using namespace std;

class Context{
public:
	Context(int num):m_num(num){
	}

	void setNum(int num){
		m_num=num;
	}
	int getNum(){
		return m_num;
	}	
	void setRes(int res){
		m_res=res;
	}
	int getRes(){
		return m_res;
	}

private:
	int m_num;
	int m_res;
};


class Expression{
public:
	virtual void interpreter(Context* context)=0;
};

class PlusExpression:public Expression{
public:
	virtual void interpreter(Context* context){
		int num=context->getNum();
		num++;
		context->setNum(num);
		context->setRes(num);
	}
};

class MinusExpression:public Expression{
public:
	virtual void interpreter(Context* context){
		int num=context->getNum();
		num--;
		context->setNum(num);
		context->setRes(num);
	}
};

int main(){
	Context* pcxt=new Context(10);
	Expression* e1=new PlusExpression();
	e1->interpreter(pcxt);

	cout<<"plusExpression: "<<pcxt->getRes()<<endl;

	Expression* e2=new MinusExpression();
	e2->interpreter(pcxt);
	cout<<"MinusExpression: "<<pcxt->getRes()<<endl;
	return 0;
}


后记:设计模式的学习到此告一段落,谢谢观看。明天开启新的学习计划。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值