上一篇介绍了结构型模式
http://blog.csdn.net/songshimvp1/article/details/48970017——代理模式、装饰模式、适配器模式(adapter)、组合模式、桥接模式(bridge)、外观模式(facade)、享元模式(flyweight)。接下来介绍行为型模式——模板模式(template)、命令模式(command)、责任链模式、策略模式、中介者模式(mediator)、观察者模式(observer)、备忘录模式(mememto)、访问者模式(visitor)、状态模式(state)、解释模式(interpreter)、迭代器模式(iterator)。
Template Method模式一般应用在具有以下条件的应用中:
(1)具有统一的操作步骤或操作过程
(2)具有不同的操作细节
(3)存在多个具有同样操作步骤的应用场景,但某些具体的操作细节却各不相同
总结:在抽象类中统一操作步骤,并规定好接口(提前定义好接口的形式、调用过程、规则);让子类实现接口。这样可以把各个具体的子类和操作步骤接耦合
但在有些情况下有必要使用一个专门的类对这种调用过程加以封装,我们把这种专门的类称作command类。(1)整个调用过程比较繁杂,或者存在多处这种调用。这时,使用Command类对该调用加以封装,便于功能的再利用。(2)调用前后需要对调用参数进行某些处理。调用前后需要进行某些额外处理,比如日志,缓存,记录历史操作等。
适用于:是将一个请求封装为一个类,从而使你可用不同的请求对客户端进行参数化;同时可对请求排队或记录请求日志,以及支持可撤销的操作。
责任链优缺点:
优点:
1、责任的分担。每个类只需要处理自己该处理的工作(不该处理的传递给下一个对象完成),明确各类的责任范围,符合类的最小封装原则。
2、可以根据需要自由组合工作流程。如工作流程发生变化,可以通过重新分配对象链便可适应新的工作流程。
3、类与类之间可以以松耦合的形式加以组织。
缺点:
因为处理时以链的形式在对象间传递消息,根据实现方式不同,有可能会影响处理的速度。
适用于:准备一组算法,并将每一个算法封装起来,使得它们可以互换。
策略模式优点:
1. 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免重复的代码。
2. 策略模式提供了可以替换继承关系的办法。继承可以处理多种算法或行为。如果不是用策略模式,那么使用算法或行为的环境类就可能会有一些子类,每一个子类提供一个不同的算法或行为。但是,这样一来算法或行为的使用者就和算法或行为本身混在一起。决定使用哪一种算法或采取哪一种行为的逻辑就和算法或行为的逻辑混合在一起,从而不可能再独立演化。继承使得动态改变算法或行为变得不可能。
3. 使用策略模式可以避免使用多重条件转移语句。多重转移语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重转移语句里面,比使用继承的办法还要原始和落后。
策略模式缺点:
1. 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。
2. 策略模式造成很多的策略类。有时候可以通过把依赖于环境的状态保存到客户端里面,而将策略类设计成可共享的,这样策略类实例可以被不同客户端使用。换言之,可以使用享元模式来减少对象的数量。
适用于:用一个中介对象,封装一些列对象(同事)的交换,中介者是各个对象不需要显示的相互作用,从而实现了耦合松散,而且可以独立的改变他们之间的交换。
中介者模式优点:
1、将系统按功能分割成更小的对象,符合类的最小设计原则;
2、对关联对象的集中控制;
3、减小类的耦合程度,明确类之间的相互关系:当类之间的关系过于复杂时,其中任何一个类的修改都会影响到其他类,不符合类的设计的开闭原则 ,而Mediator模式将原来相互依存的多对多的类之间的关系简化为Mediator控制类与其他关联类的一对多的关系,当其中一个类修改时,可以对其他关联类不产生影响(即使有修改,也集中在Mediator控制类);
4、有利于提高类的重用性;
典型应用:
(1)侦听事件驱动程序设计中的外部事件;
(2)侦听/监视某个对象的状态变化;
(3)发布者/订阅者(publisher/subscriber)模型中,当一个外部事件(新的产品,消息的出现等等)被触发时,通知邮件列表中的订阅者;
适用于:定义对象间一种一对多的依赖关系,使得每一个对象改变状态,则所有依赖于他们的对象都会得到通知。
应用场景:
如果一个对象需要保存状态并可通过undo或rollback等操作恢复到以前的状态时,可以使用Memento模式。
1)一个类需要保存它的对象的状态(相当于Originator角色);
2)设计一个类,该类只是用来保存上述对象的状态(相当于Memento角色);
3)需要的时候,Caretaker角色要求Originator返回一个Memento并加以保存;
4)undo或rollback操作时,通过Caretaker保存的Memento恢复Originator对象的状态;
适用于:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样就可以将以后的对象状态恢复到先前保存的状态。
适用于功能比较复杂的,但需要记录或维护属性历史的类;或者需要保存的属性只是众多属性中的一小部分时Originator可以根据保存的Memo还原到前一状态。
适用于:把 数据结构 和 作用于数据结构上的操作 进行解耦合;适用于数据结构比较稳定的场合
访问者模式的优点:
1,访问者模式使得增加新的操作变得很容易。如果一些操作依赖于一个复杂的结构对象的话,那么一般而言,增加新的操作会很复杂。而使用访问者模式,增加新的操作就意味着增加一个新的访问者类,因此,变得很容易。
2,访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。
3,访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。迭代子只能访问属于同一个类型等级结构的成员对象,而不能访问属于不同等级结构的对象。访问者模式可以做到这一点。
4,积累状态。每一个单独的访问者对象都集中了相关的行为,从而也就可以在访问的过程中将执行操作的状态积累在自己内部,而不是分散到很多的节点对象中。这是有益于系统维护的优点。
访问者模式的缺点:
1,增加新的节点类变得很困难。每增加一个新的节点都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作。
2,破坏封装。访问者模式要求访问者对象访问并调用每一个节点对象的操作,这隐含了一个对所有节点对象的要求:它们必须暴露一些自己的操作和内部状态。不然,访问者的访问就变得没有意义。由于访问者对象自己会积累访问操作所需的状态,从而使这些状态不再存储在节点对象中,这也是破坏封装的。
试想,如果由容器自己实现顺序遍历,那么就要直接在容器类里直接添加顺序遍历方法;如果让调用者自己实现遍历,那么就需要直接暴露数据细节给外部。Iterator模式提供一种有效的方法,可以屏蔽对象集合的容器类的实现细节,而能对容器内包含的对象元素按顺序进行有效的遍历访问。所以,Iterator模式的应用场景可以归纳为满足以下几个条件:(1)访问容器中包含的内部对象;(2)按顺序访问。
设计模式简介之——行为型模式
1、模板模式(template)
Template Method模式也叫模板方法模式,是行为模式之一,它把具有特定步骤算法中的某些必要的处理委让给抽象方法,通过子类继承对抽象方法的不同实现改变整个算法的行为。Template Method模式一般应用在具有以下条件的应用中:
(1)具有统一的操作步骤或操作过程
(2)具有不同的操作细节
(3)存在多个具有同样操作步骤的应用场景,但某些具体的操作细节却各不相同
总结:在抽象类中统一操作步骤,并规定好接口(提前定义好接口的形式、调用过程、规则);让子类实现接口。这样可以把各个具体的子类和操作步骤接耦合
class MakeCar
{
public:
virtual void MakeHead() = 0;
virtual void MakeBody() = 0;
virtual void MakeTail() = 0;
public:
void Make() //模板函数,把业务逻辑给做好
{
MakeTail();
MakeBody();
MakeHead();
}
};
class Jeep : public MakeCar
{
public:
virtual void MakeHead()
{
cout << "jeep head" << endl;
}
virtual void MakeBody()
{
cout << "jeep body" << endl;
}
virtual void MakeTail()
{
cout << "jeep tail" << endl;
}
};
class Bus : public MakeCar
{
public:
virtual void MakeHead()
{
cout << "Bus head" << endl;
}
virtual void MakeBody()
{
cout << "Bus body" << endl;
}
virtual void MakeTail()
{
cout << "Bus tail" << endl;
}
};
void main()
{
MakeCar *mycar = new Bus;
mycar->Make();
delete mycar;
cout << endl;
MakeCar *mycar2 = new Jeep;
mycar2->Make();
delete mycar2;
}
2、命令模式(command)
Command模式通过被称为Command的类封装了对目标对象的调用行为以及调用参数。在面向对象的程序设计中,一个对象调用另一个对象,一般情况下的调用过程是:创建目标对象实例;设置调用参数;调用目标对象的方法。但在有些情况下有必要使用一个专门的类对这种调用过程加以封装,我们把这种专门的类称作command类。(1)整个调用过程比较繁杂,或者存在多处这种调用。这时,使用Command类对该调用加以封装,便于功能的再利用。(2)调用前后需要对调用参数进行某些处理。调用前后需要进行某些额外处理,比如日志,缓存,记录历史操作等。
适用于:是将一个请求封装为一个类,从而使你可用不同的请求对客户端进行参数化;同时可对请求排队或记录请求日志,以及支持可撤销的操作。
// 发起者、接收者、命令
#include <iostream>
using namespace std;
#include "list"
//医生
class Doctor
{
public:
void treat_eye()
{
cout << "医生 治疗 眼科病" << endl;
}
void treat_nose()
{
cout << "医生 治疗 鼻科病" << endl;
}
};
//命令
class Command //基类
{
public:
virtual void treat() = 0;
};
class CommandTreatEye : public Command //具体命令
{
public:
CommandTreatEye(Doctor *doctor)
{
m_doctor = doctor;
}
void treat()
{
m_doctor->treat_eye();
}
private:
Doctor *m_doctor;
};
class CommandTreatNose : public Command //具体命令
{
public:
CommandTreatNose(Doctor *doctor)
{
m_doctor = doctor;
}
void treat()
{
m_doctor->treat_nose();
}
private:
Doctor *m_doctor;
};
//护士——单个下命令
class BeautyNurse //命令的发起者
{
public:
BeautyNurse(Command *command)
{
this->command = command;
}
public:
void SubmittedCase() //提交病例,下命令
{
command->treat();
}
protected:
private:
Command *command; //持有命令
};
//护士长——批量下命令
class HeadNurse
{
public:
HeadNurse()
{
m_list.clear();
}
public:
void setCommand(Command *command)
{
m_list.push_back(command);
}
void SubmittedCase() //提交病例 下命令
{
for (list<Command *>::iterator it = m_list.begin(); it != m_list.end(); it++)
{
(*it)->treat();
}
}
private:
list<Command *> m_list; //持有批量命令
};
void main01()
{
//1 医生直接看病
/*
Doctor *doctor = new Doctor ;
doctor->treat_eye();
delete doctor;
*/
//2 通过一个命令 医生通过 命令 治疗 治病
Doctor *doctor = new Doctor;
Command * command = new CommandTreatEye(doctor);
command->treat();
delete command;
delete doctor;
}
void main02()
{
//3 护士提交简历 给医生看病
BeautyNurse *beautynurse = NULL;
Doctor *doctor = NULL;
Command *command = NULL;
doctor = new Doctor;
command = new CommandTreatEye(doctor);
//command = new CommandTreatNose(doctor); //客户端可以面向命令进行编程了,实现了命令和客户端的解耦合
beautynurse = new BeautyNurse(command);
beautynurse->SubmittedCase();
delete doctor;
delete command;
delete beautynurse;
}
//4 通过护士长 批量的下命令
void main03()
{
//护士长提交简历 给医生看病
HeadNurse *headnurse = NULL;
Doctor *doctor = NULL;
Command *command1 = NULL;
Command *command2 = NULL;
doctor = new Doctor;
command1 = new CommandTreatEye(doctor);
command2 = new CommandTreatNose(doctor);
headnurse = new HeadNurse(); //new 护士长
headnurse->setCommand(command1);//收集命令
headnurse->setCommand(command2);
headnurse->SubmittedCase(); //护士长 批量下命令
delete doctor;
delete command1;
delete command2;
delete headnurse;
}
void main()
{
//main01();
//main02();
main03();
}
3、责任链模式
Chain of Responsibility(CoR)模式,构造一系列分别担当不同的职责的类的对象来共同完成一个任务,这些类的对象之间像链条一样紧密相连,所以被称作职责链模式。比如政府部分的某项工作,县政府先完成自己能处理的部分,不能处理的部分交给省政府,省政府再完成自己职责范围内的部分,不能处理的部分交给中央政府,中央政府最后完成该项工作。再比如:软件窗口的消息传播。适用于:链条式处理事情。工作流程化、消息处理流程化、事物流程化;责任链优缺点:
优点:
1、责任的分担。每个类只需要处理自己该处理的工作(不该处理的传递给下一个对象完成),明确各类的责任范围,符合类的最小封装原则。
2、可以根据需要自由组合工作流程。如工作流程发生变化,可以通过重新分配对象链便可适应新的工作流程。
3、类与类之间可以以松耦合的形式加以组织。
缺点:
因为处理时以链的形式在对象间传递消息,根据实现方式不同,有可能会影响处理的速度。
#include <iostream>
using namespace std;
/*
struct Teacher
{
char name;
int age;
Teacher *next; //链!下一个处理单元
};
*/
//“造完”车以后,需要把任务 传递下去
class CarHandle
{
public:
virtual void HandleCar() = 0;
CarHandle *setNextHandle(CarHandle *handle)
{
m_handle = handle;
return m_handle;
}
protected:
CarHandle *m_handle; //指向自己,类似struct中的Teacher *next,下一个处理单元
};
class HeadCarHandle : public CarHandle
{
public:
virtual void HandleCar()
{
cout << "造 车头" << endl;
//造完 车头 以后,把任务递交给 下一个处理者
if (m_handle != NULL)
{
m_handle->HandleCar();
}
}
};
class BodyCarHandle : public CarHandle
{
public:
virtual void HandleCar()
{
cout << "造 车身" << endl;
//造完 车身 以后,把任务递交给 下一个处理者
if (m_handle != NULL)
{
m_handle->HandleCar();
}
}
};
class TailCarHandle : public CarHandle
{
public:
virtual void HandleCar()
{
cout << "造 车尾" << endl;
//造完 车尾 以后,把任务递交给 下一个处理者
if (m_handle != NULL)
{
m_handle->HandleCar();
}
}
};
void main()
{
//责任链 不是 “伪面向过程编程”!
CarHandle *headHandle = new HeadCarHandle;
CarHandle *bodyHandle = new BodyCarHandle;
CarHandle *tailHandle = new TailCarHandle;
//任务的处理关系
/*
headHandle->setNextHandle(bodyHandle);
bodyHandle->setNextHandle(tailHandle);
tailHandle->setNextHandle(NULL);
*/
//业务逻辑可以灵活改变,不会被写死到客户端
// headHandle--->bodyHandle--->tailHandle
// headHandle--->tailHandle--->bodyHandle
headHandle->setNextHandle(tailHandle); //生成责任链
tailHandle->setNextHandle(bodyHandle);
bodyHandle->setNextHandle(NULL);
headHandle->HandleCar(); //处理
delete headHandle;
delete bodyHandle;
delete tailHandle;
}
4、策略模式(strategy)
Strategy模式,策略模式,是行为模式之一,它对一系列的算法加以封装,为所有算法定义一个抽象的算法接口,并通过继承该抽象算法接口对所有的算法加以封装和实现,具体的算法选择交由客户端决定(策略)。Strategy模式主要用来平滑地处理算法的切换 。适用于:准备一组算法,并将每一个算法封装起来,使得它们可以互换。
策略模式优点:
1. 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免重复的代码。
2. 策略模式提供了可以替换继承关系的办法。继承可以处理多种算法或行为。如果不是用策略模式,那么使用算法或行为的环境类就可能会有一些子类,每一个子类提供一个不同的算法或行为。但是,这样一来算法或行为的使用者就和算法或行为本身混在一起。决定使用哪一种算法或采取哪一种行为的逻辑就和算法或行为的逻辑混合在一起,从而不可能再独立演化。继承使得动态改变算法或行为变得不可能。
3. 使用策略模式可以避免使用多重条件转移语句。多重转移语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重转移语句里面,比使用继承的办法还要原始和落后。
策略模式缺点:
1. 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。
2. 策略模式造成很多的策略类。有时候可以通过把依赖于环境的状态保存到客户端里面,而将策略类设计成可共享的,这样策略类实例可以被不同客户端使用。换言之,可以使用享元模式来减少对象的数量。
#include <iostream>
using namespace std;
class Strategy //策略抽象
{
public:
virtual void crypt() = 0;
};
//对称加密:速度快 加密大数据块文件;特点:加密密钥和解密密钥是一样的.
class AES : public Strategy
{
public:
virtual void crypt()
{
cout << "AES 加密算法" << endl;
}
};
//非对称加密:加密速度慢 加密强度高 安全性高;特点: 加密密钥和解密密钥不一样,密钥对(公钥 和 私钥)
class DES : public Strategy
{
public:
virtual void crypt()
{
cout << "DES 加密算法" << endl;
}
};
class Context //将算法的逻辑抽象接口封装到该类(Context)中
{
public:
void setStrategy(Strategy *strategy)
{
this->strategy = strategy;
}
void myoperator()
{
strategy->crypt();
}
private:
Strategy *strategy;
};
void main()
{
/*
//1
DES *des = new DES;
des->crypt();
delete des;
*/
Strategy *strategy = NULL;
//strategy = new DES;
strategy = new AES;
Context *context = new Context;
context->setStrategy(strategy);
context->myoperator();
delete strategy;
delete context;
}
5、中介者模式(mediator)
Mediator模式是行为模式之一,在Mediator模式中,类之间的交互行为被统一放在Mediator的对象中,对象通过Mediator对象同其他对象交互,Mediator对象起着控制器的作用。适用于:用一个中介对象,封装一些列对象(同事)的交换,中介者是各个对象不需要显示的相互作用,从而实现了耦合松散,而且可以独立的改变他们之间的交换。
中介者模式优点:
1、将系统按功能分割成更小的对象,符合类的最小设计原则;
2、对关联对象的集中控制;
3、减小类的耦合程度,明确类之间的相互关系:当类之间的关系过于复杂时,其中任何一个类的修改都会影响到其他类,不符合类的设计的开闭原则 ,而Mediator模式将原来相互依存的多对多的类之间的关系简化为Mediator控制类与其他关联类的一对多的关系,当其中一个类修改时,可以对其他关联类不产生影响(即使有修改,也集中在Mediator控制类);
4、有利于提高类的重用性;
class Mediator;
class Person
{
public:
Person(string name, int sex, int condi, Mediator *m)
{
m_name = name;
m_sex = sex;
m_condi = condi;
mediator = m;
}
string getName()
{
return m_name;
}
int getSex()
{
return m_sex;
}
int getCondi()
{
return m_condi;
}
virtual void getParter(Person *p) = 0;
protected:
string m_name;
int m_sex;
int m_condi;
Mediator *mediator;
};
class Mediator //中介者
{
public:
void setMan(Person *man)
{
pMan = man;
}
void setWoman(Person *woman)
{
pWoman = woman;
}
public:
virtual void getParter()
{
if (pWoman->getSex() == pMan->getSex())
{
cout << "同性恋 之间 不能找对象!" << endl;
}
if (pWoman->getCondi() == pMan->getCondi())
{
cout << pWoman->getName() << " 和 " << pMan->getName() << "绝配 " << endl;
}
else
{
cout << pWoman->getName() << " 和 " << pMan->getName() << "不配 " << endl;
}
}
private:
Person *pMan; //男
//list<Person *> m_list;
Person *pWoman; //女
};
class Man : public Person //男
{
public:
Man(string name, int sex, int condi, Mediator *m) : Person(name, sex, condi, m)
{
}
virtual void getParter(Person *p)
{
mediator->setMan(this);
mediator->setWoman(p);
mediator->getParter(); //找对象
}
};
class Woman : public Person //女
{
public:
Woman(string name, int sex, int condi, Mediator *m) : Person(name, sex, condi, m)
{
}
virtual void getParter(Person *p)
{
mediator->setMan(p);
mediator->setWoman(this);
mediator->getParter(); //找对象
}
};
void main()
{
//string name, int sex, int condi
Mediator *m = new Mediator;
Person *xiaofang = new Woman("小芳", 2, 5, m);
Person *zhangsan = new Man("张三", 1, 4, m);
Person *lisi = new Man("李四", 1, 5, m);
xiaofang->getParter(zhangsan);
xiaofang->getParter(lisi);
}
6、观察者模式(observer)
Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。Observer模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步。典型应用:
(1)侦听事件驱动程序设计中的外部事件;
(2)侦听/监视某个对象的状态变化;
(3)发布者/订阅者(publisher/subscriber)模型中,当一个外部事件(新的产品,消息的出现等等)被触发时,通知邮件列表中的订阅者;
适用于:定义对象间一种一对多的依赖关系,使得每一个对象改变状态,则所有依赖于他们的对象都会得到通知。
class Secretary;
//观察者(玩游戏的同事)
class PlayserObserver
{
public:
PlayserObserver(Secretary *secretary)
{
this->m_secretary = secretary;
}
void update(string action)
{
cout << "action:" << action << endl;
cout << "收到!" << endl;
cout << endl;
}
private:
Secretary *m_secretary;
};
//秘书(通知者)
class Secretary
{
public:
Secretary()
{
m_list.clear();
}
void setPlayserObserver(PlayserObserver *o)
{
m_list.push_back(o);
}
void Notify(string info)
{
//给所有的 观察者 发送 情报
for (list<PlayserObserver *>::iterator it = m_list.begin(); it != m_list.end(); it++)
{
(*it)->update(info);
}
}
private:
list<PlayserObserver *> m_list;
};
void main07()
{
//玩游戏的多个同事同时监听秘书发来的消息,以便做出及时的状态更新!
Secretary *secretary = NULL;
PlayserObserver *po1 = NULL;
PlayserObserver *po2 = NULL;
secretary = new Secretary;
po1 = new PlayserObserver(secretary);
po2 = new PlayserObserver(secretary);
secretary->setPlayserObserver(po1);
secretary->setPlayserObserver(po2);
secretary->Notify("老板来了!");//在list中的多个监听对象,都会收到该通知!
secretary->Notify("老板走了!");//在list中的多个监听对象,都会收到该通知!
delete secretary;
delete po1;
delete po2;
}
7、备忘录模式(mememto)
Memento模式,备忘录模式,是行为模式之一,它的作用是保存对象的内部状态,并在需要的时候(undo/rollback)恢复对象以前的状态。适用于:(1)在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样就可以将以后的对象状态恢复到先前保存的状态;(2)功能比较复杂的,但需要记录或维护属性历史的类;或者需要保存的属性只是众多属性中的一小部分时Originator可以根据保存的Memo还原到前一状态。应用场景:
如果一个对象需要保存状态并可通过undo或rollback等操作恢复到以前的状态时,可以使用Memento模式。
1)一个类需要保存它的对象的状态(相当于Originator角色);
2)设计一个类,该类只是用来保存上述对象的状态(相当于Memento角色);
3)需要的时候,Caretaker角色要求Originator返回一个Memento并加以保存;
4)undo或rollback操作时,通过Caretaker保存的Memento恢复Originator对象的状态;
适用于:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样就可以将以后的对象状态恢复到先前保存的状态。
适用于功能比较复杂的,但需要记录或维护属性历史的类;或者需要保存的属性只是众多属性中的一小部分时Originator可以根据保存的Memo还原到前一状态。
//Caretaker 管理者
// MememTo 备忘录
class MememTo
{
public:
MememTo(string name, int age)
{
m_name = name;
m_age = age;
}
string getName()
{
return m_name;
}
int getAge()
{
return m_age;
}
void setName(string name)
{
m_name = name;
}
void setAge(int age)
{
m_age = age;
}
private:
string m_name;
int m_age;
};
class Person
{
public:
Person(string name, int age)
{
m_name = name;
m_age = age;
}
string getName()
{
return m_name;
}
int getAge()
{
return m_age;
}
void setName(string name)
{
m_name = name;
}
void setAge(int age)
{
m_age = age;
}
//保存
MememTo* createMemto()
{
return new MememTo(m_name, m_age);
}
//还原
void setMemTo(MememTo *mememto)
{
m_age = mememto->getAge();
m_name = mememto->getName();
}
void print()
{
cout << "m_name:" << m_name << " m_age:" << m_age << endl;
}
private:
string m_name;
int m_age;
};
//管理者
class Caretaker
{
public:
Caretaker(MememTo *memto)
{
this->memto = memto;
}
MememTo* getMemTo()
{
return this->memto;
}
void setMemTo(MememTo * memto)
{
this->memto = memto;
}
private:
MememTo *memto;
};
void main001()
{
Person *p = new Person("zhangsan", 33);
p->print();
cout << endl;
//创建Person对象的一个状态
MememTo *m = NULL;
m = p->createMemto();
p->setAge(42);
p->print();
cout << "还原旧的状态:" << endl;
p->setMemTo(m);
p->print();
delete m;
delete p;
}
//加入管理者 Caretaker类
void main0002()
{
Caretaker *caretaker = NULL;
Person *p = new Person("zhangsan", 33);
p->print();
cout << endl;
//创建Person对象的一个状态
//MememTo *m = NULL;
caretaker = new Caretaker(p->createMemto());
//m = p->createMemto();
p->setAge(42);
p->print();
cout << "还原旧的状态:" << endl;
p->setMemTo(caretaker->getMemTo());
p->print();
delete caretaker;
delete p;
}
void main()
{
//main001();
main0002();
}
8、访问者模式(visitor)
Visitor模式,访问者模式,是行为模式之一,它分离对象的数据和行为,使用Visitor模式,可以不修改已有类的情况下,增加新的操作角色和职责。适用于:把 数据结构 和 作用于数据结构上的操作 进行解耦合;适用于数据结构比较稳定的场合
访问者模式的优点:
1,访问者模式使得增加新的操作变得很容易。如果一些操作依赖于一个复杂的结构对象的话,那么一般而言,增加新的操作会很复杂。而使用访问者模式,增加新的操作就意味着增加一个新的访问者类,因此,变得很容易。
2,访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。
3,访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。迭代子只能访问属于同一个类型等级结构的成员对象,而不能访问属于不同等级结构的对象。访问者模式可以做到这一点。
4,积累状态。每一个单独的访问者对象都集中了相关的行为,从而也就可以在访问的过程中将执行操作的状态积累在自己内部,而不是分散到很多的节点对象中。这是有益于系统维护的优点。
访问者模式的缺点:
1,增加新的节点类变得很困难。每增加一个新的节点都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作。
2,破坏封装。访问者模式要求访问者对象访问并调用每一个节点对象的操作,这隐含了一个对所有节点对象的要求:它们必须暴露一些自己的操作和内部状态。不然,访问者的访问就变得没有意义。由于访问者对象自己会积累访问操作所需的状态,从而使这些状态不再存储在节点对象中,这也是破坏封装的。
9、状态模式(state)
State模式,状态模式,是行为设计模式的一种。State模式允许通过改变对象的内部状态而改变对象的行为,这个对象表现得就好像修改了它的类一样。 状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转译到表现不同状态的一系列类当中,可以把复杂的判断逻辑简化。适用于:对象的行为,依赖于它所处的当前状态。行为随状态改变而改变的场景。
#include <iostream>
using namespace std;
class Worker;
class State
{
public:
virtual void doSomeThing(Worker *w) = 0;
};
class Worker
{
public:
Worker();
int getHour()
{
return m_hour;
}
void setHour(int hour) //改变状态 7
{
m_hour = hour;
}
State* getCurrentState()
{
return m_currstate;
}
void setCurrentState(State* state)
{
m_currstate = state;
}
void doSomeThing()
{
m_currstate->doSomeThing(this);
}
private:
int m_hour;
State *m_currstate; //对象的当前状态
};
class State1 : public State
{
public:
void doSomeThing(Worker *w);
};
class State2 : public State
{
public:
void doSomeThing(Worker *w);
};
void State1::doSomeThing(Worker *w)
{
if (w->getHour() == 7 || w->getHour() == 8)
{
cout << "吃早饭" << endl;
}
else
{
//状态1 不满足,要转到状态2
delete w->getCurrentState(); //干掉状态1
w->setCurrentState(new State2); //换成状态2
w->getCurrentState()->doSomeThing(w);
}
}
void State2::doSomeThing(Worker *w)
{
if (w->getHour() == 9 || w->getHour() == 10)
{
cout << "工作" << endl;
}
else
{
delete w->getCurrentState(); //状态2 不满足 要转到状态3 后者恢复到初始化状态
w->setCurrentState(new State1); //恢复到当初状态
cout << "当前时间点:" << w->getHour() << "未知状态" << endl;
}
}
Worker::Worker()
{
m_currstate = new State1;
}
void main()
{
Worker *w1 = new Worker;
w1->setHour(7);
w1->doSomeThing();
w1->setHour(9);
w1->doSomeThing();
delete w1;
cout << "hello..." << endl;
system("pause");
return;
}
10、解释器模式(interpreter)
Interpreter模式的目的是:使用一个解释器为用户提供一个一门定义语言的语法表示的解释器,然后通过这个解释器来解释语言中的句子。(一些应用提供了内建的的脚本或者宏语言来让用户可以定义他们能够在系统中进行的操作。)Interpreter模式提供了这样一个实现语法解释器的框架。#include <iostream>
using namespace std;
// Context
// Expression
// PlusExpression MinusExpression
class Context
{
public:
Context(int num)
{
this->m_num = num;
}
int getNum()
{
return m_num;
}
int getRes()
{
return m_res;
}
void setNum(int num)
{
this->m_num = num;
}
void setRes(int res)
{
this->m_res = res;
}
private:
int m_num; //输入
int m_res; //输出
};
class Expression //解释器
{
public:
virtual void interpreter(Context *context) = 0;
private:
Context *m_context; //关联Context
};
//加法
class PlusExpression : public Expression
{
public:
PlusExpression()
{
this->context = NULL;
}
virtual void interpreter(Context *context)
{
int num = context->getNum();
num++;
context->setNum(num);
context->setRes(num);
}
private:
Context *context;
};
// 减法
class MinusExpression : public Expression
{
public:
MinusExpression()
{
this->context = NULL;
}
virtual void interpreter(Context *context)
{
int num = context->getNum();
num--;
context->setNum(num);
context->setRes(num);
}
private:
Context *context;
};
void main()
{
Expression *expression = NULL;
Context *context = NULL;
Expression *expression2 = NULL;
context = new Context(10);
cout << context->getNum() << endl;
expression = new PlusExpression;
expression->interpreter(context);
cout << context->getRes() << endl;
expression2 = new MinusExpression;
expression2->interpreter(context);
cout << context->getRes() << endl;
}
11、迭代器模式(iterator)
Iterator模式,迭代模式,是行为模式之一,它 把对容器中包含的内部对象的访问 委让给 外部类,使用Iterator(遍历)按顺序进行遍历访问的设计模式。试想,如果由容器自己实现顺序遍历,那么就要直接在容器类里直接添加顺序遍历方法;如果让调用者自己实现遍历,那么就需要直接暴露数据细节给外部。Iterator模式提供一种有效的方法,可以屏蔽对象集合的容器类的实现细节,而能对容器内包含的对象元素按顺序进行有效的遍历访问。所以,Iterator模式的应用场景可以归纳为满足以下几个条件:(1)访问容器中包含的内部对象;(2)按顺序访问。
#include <iostream>
using namespace std;
// MyIterator、Aggregate、ContreteIterator、ConcreteAggregate
// a b c d
// ▲
typedef int Object; //用int型模拟变量
#define SIZE 5
//迭代器抽象层
class MyIterator
{
public:
virtual void First() = 0; //让迭代器位置回到首位
virtual void Next() = 0;
virtual bool IsDone() = 0; //检查迭代器是否遍历完毕
virtual Object CurrentItem() = 0; //获取一个对象,用上述的object来模拟对象
};
//集合抽象层
class Aggregate
{
public:
virtual MyIterator *CreateIterator() = 0; //创建迭代器
virtual Object getItem(int index) = 0; //获取当前元素
virtual int getSize() = 0; //获取集合大小
};
//具体的迭代器
class ContreteIterator : public MyIterator
{
public:
ContreteIterator(Aggregate *ag)
{
_ag = ag;
_current_index = 0;
}
virtual void First()
{
_current_index = 0; //让当前 游标 回到位置0
}
virtual void Next()
{
if (_current_index < _ag->getSize())
{
_current_index++;
}
}
virtual bool IsDone()
{
return (_current_index == _ag->getSize());
}
virtual Object CurrentItem()
{
return _ag->getItem(_current_index);
}
private:
int _current_index;
Aggregate *_ag;
};
//具体的集合
class ConcreteAggregate : public Aggregate
{
public:
ConcreteAggregate()
{
for (int i = 0; i<SIZE; i++)
{
object[i] = i + 100;
}
}
virtual MyIterator *CreateIterator()
{
return new ContreteIterator(this); //让迭代器 持有一个 集合的 引用
}
virtual Object getItem(int index)
{
return object[index];
}
virtual int getSize()
{
return SIZE;
}
private:
Object object[SIZE];
};
void main()
{
Aggregate *ag = new ConcreteAggregate;
MyIterator *it = ag->CreateIterator();
for (; !(it->IsDone()); it->Next())
{
cout << it->CurrentItem() << " ";
}
delete it;
delete ag;
}