设计模式(Design Pattern)代表了最佳实践。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决问题。
设计模式是一套被反复使用的、多人知晓的、经过分类编目的、代码设计经验的总结。
使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。
设计模式是软件设计中常见问题的典型解决方案。每个模式就像一张蓝图,可以通过对齐进行定制来解决代码中的特定设计问题。
类的职责要单一,不能将太多的职责放在一个类中。
**对扩展开放,对修改关闭。**在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类。
是面向对象设计的基本原则之一。该原则说,任何基类可以出现的地方,子类一定可以出现。LSP是继承复用的基石,只有派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤是抽象化,而基类和子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
这个原则是开闭原则的基础,具体内容为:针对接口编程,依赖于抽象而不依赖于具体。
使用多个隔离的接口,比使用单个接口更好。即降低类之间的耦合度。
一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
尽量使用合成/聚合的方式,而不是使用继承。
单例模式是一种创建型设计模式,能够保证一个类只有一个实例,并提供一个访问该实例的全局节点。
1,保证一个类只有一个实例。最常见的原因是控制某些共享资源的访问权限。
2,为该实例提供一个全局访问节点。和全局变量一样,单例模式也允许在程序的任何地方访问特定对象。但是他可以保护该实例不被其他代码覆盖。
所有实例的实现都包含以下两个相同的步骤:
new
运算符如果代码能够访问单例类,那他就能调用单例类的静态方法。无论何时调用该方法,他总是能够返回相同的对象。
单例(Singleton)类声明一个名为getInstance
获取实例的静态方法来返回其所属类的一个相同实例。
单例的构造方法必须对客户端代码隐藏,调用获取实例方法必须是获取单例对象的唯一方式。
获取实例
方法, 即 getInstance 中的代码即可实现。// 懒汉式,线程不安全
class Singleton{
public:
static Singleton* getInstance(){
}
private:
Singleton(){
}
static Singleton *singleton;
};
Singleton* Singleton::singleton = NULL;
Singleton* Singleton::getInstance(){
if(singleton == NULL)
singleton = new Singleton();
return singleton;
}
// 懒汉式,线程安全
#include
class Singleton {
private:
Singleton() {
}
static Singleton* singleton;
static pthread_mutex_t mutex;
public:
static Singleton* getInstance();
};
pthread_mutex_t Singleton::mutex = PTHREAD_MUTEX_INITIALIZER;
Singleton* Singleton::singleton = NULL;
Singleton* Singleton::getInstance(){
if(singleton == NULL){
pthread_mutex_lock(&mutex);
if(singleton == NULL)
singleton = new Singleton();
pthread_mutex_unlock(&mutex);
}
return singleton;
}
// 饿汉式,线程安全,初始就创建一个实例
class Singleton{
private:
Singleton (){
}
static Singleton* singleton;
public:
static Singleton* getInstance(){
return singleton;
}
};
Singleton* Singleton::singleton = new Singleton();
优点:
缺点:
工厂方法模式是一种创建型设计模式, 其在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型。
工厂方法模式建议使用特殊的工厂方法代替对于对象构造函数的直接调用(即使用new运算符)。
但是需要注意:仅当这些产品具有共同的基类或者接口时,子类才能返回不同类型的产品。同时基类中的工厂方法还应将其返回类型声明为这一共有接口。
调用工厂方法的代码(通常被视为客户端代码)无需了解不同子类返回实际对象之间的差别。客户端将所有产品视为抽象的运输
。客户端都知道所有运输对象都提供交付
方法,但是并不关心其具体实现方式。
例子:生产处理器的厂商,一个工厂生产处理器A,一个生产处理器B
class Core{
public:
virutal void show() = 0;
};
// 处理器A
class CoreA: public Core{
public:
void show(){
cout << "Core A" << endl;}
};
// 处理器B
class CoreB: public Core{
public:
void show(){
cout << "Core B" << endl;}
};
class Factory{
public:
virtual Core* CreateCore() = 0;
};
// 生产处理器A的工厂
class FactoryA: Factory{
public:
CoreA* CreateCore(){
return new CoreA;}
};
// 生产处理器B的工厂
class FactoryB: Factory{
public:
CoreB* CreateCore(){
return new CoreB;}
};
优点:
缺点:
抽象工厂模式是一种创建型设计模式, 它能创建一系列相关的对象, 而无需指定其具体类。
抽象工厂模式建议为系列中的每件产品明确声明接口 (例如椅子、 沙发或咖啡桌)。 然后, 确保所有产品变体都继承这些接口。 例如, 所有风格的椅子都实现 椅子
接口; 所有风格的咖啡桌都实现 咖啡桌
接口, 以此类推。
例子:生产处理器的厂商,一个工厂生产处理器A,一个生产处理器B,同时公式发展迅速,推出了很多不同种类的处理器(单核或多核),在c++实现中,就需要定义一个个的工厂类。
// 单核
class SingleCore{
public:
virtual void show() = 0;
};
class SingleCoreA{
public:
void show(){
cout << "SingleCore A" << endl;}
};
class SingleCoreB{
public:
void show(){
cout << "SingleCore B" << endl;}
};
// 多核
class MultiCore{
public:
virtual void show() = 0;
};
class MultiCoreA{
public:
void show(){
cout << "MultiCore A" << endl;}
};
class MultiCoreB{
public:
void show(){
cout << "MultiCore B" << endl;}
};
// 工厂
class Factory{
public:
virtual SingleCore* CreateSingleCore() = 0;
virtual MultiCore* CreateMultiCore() = 0;
};
// 工厂A,专门生产A处理器
class FactoryA: Factory{
public:
SingleCore* CreateSingleCore(){
return new SingleCoreA;}
MultiCore* CreateMultiCore(){
return new MultiCoreA;}
};
// 工厂B,专门生产B处理器
class FactoryB: Factory{
public:
SingleCore* CreateSingleCore(){
return new SingleCoreB;}
MultiCore* CreateMultiCore(){
return new MultiCoreB;}
};
优点:
缺点:
生成器模式是一种创建型设计模式, 使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。
生成器模式建议将对象构造代码从产品类中抽取出来, 并将其放在一个名为生成器的独立对象中。
生成器模式让你能够分步骤创建复杂对象。 生成器不允许其他对象访问正在创建中的产品。
该模式会将对象构造过程划分为一组步骤,每次创建对象时, 你都需要通过生成器对象执行一系列步骤。 重点在于你无需调用所有步骤, 而只需调用创建特定对象配置所需的那些步骤即可。
当你需要创建不同形式的产品时, 其中的一些构造步骤可能需要不同的实现。
在这种情况下, 你可以创建多个不同的生成器, 用不同方式实现一组相同的创建步骤。 然后你就可以在创建过程中使用这些生成器 (例如按顺序调用多个构造步骤) 来生成不同类型的对象。
**主管:**可以进一步将用于创建产品的一系列生成器步骤调用抽取成为单独的主管类。 主管类可定义创建步骤的执行顺序, 而生成器则提供这些步骤的实现。
例子:以建造小人为例
class Builder{
public:
virtual void BuildHead(){
}
virtual void BuildBody(){
}
virtual void BuildLeftArm(){
}
virtual void BuildRightArm(){
}
virtual void BuildLeftLeg(){
}
virtual void BuildRightLeg(){
}
};
class ThinBuilder: Builder{
public:
void BuildHead(){
cout << "Build Thin Head" << endl;}
void BuildBody(){
cout << "Build Thin Body" << endl;}
void BuildLeftArm(){
cout << "Build Thin LeftArm" << endl;}
void BuildRightArm(){
cout << "Build Thin RightArm" << endl;}
void BuildLeftLeg(){
cout << "Build Thin LeftLeg" << endl;}
void BuildRightLeg(){
cout << "Build Thin RightLeg" << endl;}
};
class FatBuilder: Builder{
public:
void BuildHead(){
cout << "Build Fat Head" << endl;}
void BuildBody(){
cout << "Build Fat Body" << endl;}
void BuildLeftArm(){
cout << "Build Fat LeftArm" << endl;}
void BuildRightArm(){
cout << "Build Fat RightArm" << endl;}
void BuildLeftLeg(){
cout << "Build Fat LeftLeg" << endl;}
void BuildRightLeg(){
cout << "Build Fat RightLeg" << endl;}
};
class Director{
private:
Builder* m_pBuilder;
public:
Director(Builder* builder){
m_pBuilder = builder;}
void Create(){
m_pBuilder->BuildHead();
m_pBuilder->BuildBody();
m_pBuilder->BuildLeftArm();
m_pBuilder->BuildRightArm();
m_pBuilder->BuildLeftLeg();
m_pBuilder->BuildRightLeg();
}
};
// 客户端使用
int main(){
ThinBuilder thin;
Director director(&thin);
director.Create();
retun 0;
}
优点:
缺点:
原型模式是一种创建型设计模式, 使你能够复制已有对象, 而又无需使代码依赖它们所属的类。
原型模式将克隆过程委派给被克隆的实际对象。 模式为所有支持克隆的对象声明了一个通用接口, 该接口让你能够克隆对象, 同时又无需将代码和对象所属类耦合。 通常情况下, 这样的接口中仅包含一个 克隆
方法。
其运作方式如下: 创建一系列不同类型的对象并不同的方式对其进行配置。 如果所需对象与预先配置的对象相同, 那么你只需克隆原型即可, 无需新建一个对象。
克隆
方法。 如果你已有类层次结构, 则只需在其所有类中添加该方法即可。new
运算符调用原型版本的构造函数。 注意, 每个类都必须显式重写克隆方法并使用自身类名调用 new
运算符。 否则, 克隆方法可能会生成父类的对象。例如:简历打印。原始的手稿相当于原型,通过复印创造出更多的新简历是原型模式的基本思想。
// 父类
class Resume{
protected:
char* name;
public:
Result(){
}
virtual ~Result(){
}
virtual Resume* clone(){
return NULL;}
virtual void Set(char* str){
}
virtual void Show(){
}
};
class ResumeA: public Resume{
public:
ResumeA(const char* str);
ResumeA(const ResumeA &r);
~ResumeA();
ResuleA* Clone();
void show();
};
ResumeA::ResumeA(const char* str){
if(str == NULL){
name = new char[1];
name[0] = '\0';
}
else{
name = new char[strlen(str)+1];
strcpy(name, str);
}
}
ResumeA::~ResumeA(){
delete[] name;}
ResumeA::ResumeA(const Resume& r){
name = new char[strlen(r.name)+1];
strcpy(name, r.name);
}
ResumeA* ResumeA::Clone(){
return new ResumeA(*this);
}
void ResumeA::Show(){
cout << "ResumeA name:" << name << endl;
}
// 客户端
int main(){
Resume* r1 = new ResumeA("A");
Resume* r2 = new ResumeB("B");
Resume* r3 = r1->Clone();
Resume* r4 = r2->Clone();
r1->Show();r2->Show();
delete r1; delete r2;
r1 = r2 = NULL;
// 深拷贝对于r3,r4无影响
r3->Show(); r4->Show();
delete r3; delete r4;
r3 = r4 = NULL;
return 0;
}
优点:
缺点:
适配器模式是一种结构型设计模式, 它能使接口不兼容的对象能够相互合作。
对象适配器:
类适配器:
STL中就用到了适配器模式。STL中实现了一种数据结构为双端队列(deque),支持前后两端的插入和删除。STL实现栈和队列时,没有从头开始定义他们,而是直接使用双端队列实现的。这里双端队列就扮演了适配器的角色。队列用到了他的后端插入,前端删除。栈用到了后端插入,后端删除。
// 双端队列
class Deque{
public:
void push_back(int x){
cout << "deque push_back" << endl;}
void push_front(int x){
cout << "deque push_front" << endl;}
void pop_back(){
cout << "deque pop_back" << endl;}
void pop_front(){
cout << "deque pop_front" << endl;}
};
// 顺序容器
class Sequence{
public:
virtual void push(int x) = 0;
virtual void pop() = 0;
};
// 栈
class Stack::Sequence{
public:
void push(int x){
deque.push_back(x);}
void pop(){
deque.pop_back();}
private:
Deque deque;
};
// 队列
class Queue::Sequence{
public:
void push(int x){
deque.push_back(x);}
void pop(){
deque.pop_front();}
private:
Deque deque;
};
int main(){
Sequence *s1 = new Stack();
Sequence *s2 = new Queue();
s1->push(1);s1->pop();
s2->push(2);s2->pop();
delete s1; delete s2;
s1 = s2 = NULL:
return 0;
}
优点:
缺点:
桥接模式是一种结构型设计模式, 可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构, 从而能在开发时分别使用。
问题的根本原因是我们试图在两个独立的维度—形状与颜色—上扩展形状类。 这在处理类继承时是很常见的问题。
桥接模式通过将继承改为组合的方式来解决这个问题。 具体来说, 就是抽取其中一个维度并使之成为独立的类层次, 这样就可以在初始类中引用这个新层次的对象, 从而使得一个类不必拥有所有的状态和行为。
例子:考虑装操作系统,有多种配置的计算机,同样有多款操作系统,如何使用桥接模式呢?可以将操作系统和计算机分别抽象出来,减少他们的耦合度。
// 操作系统
class OS{
public:
virtual void InstallOS_Imp()
};
class WindowOS: public OS{
public:
void InstallOS_Imp(){
cout << "Install Window OS" << endl;}
};
class LinuxOS: public OS{
public:
void InstallOS_Imp(){
cout << "Install Linux OS" << endl;}
};
class MacOS: public OS{
public:
void InstallOS_Imp(){
cout << "Install Mac OS" << endl;}
};
// 计算机
class Computer{
public:
vitual void InstallOS(OS *os){
}
};
class DellComputer: public Computer{
public:
void Install(OS *os){
os->InstallOS_Imp();}
};
class HPComputer: public Computer{
public:
void Install(OS *os){
os->InstallOS_Imp();}
};
class AppleComputer: public Computer{
public:
void Install(OS *os){
os->InstallOS_Imp();}
};
int main(){
OS *os1 = new WindowOS();
OS *os2 = new LinuxOS();
OS *os3 = new MacOS();
Computer *computer1 = new AppleComputer();
computer1->Install(os3);
return 0;
}
优点:
组合模式是一种结构性设计模式,你可以使用它将对象组合成树状结构,并且能像使用独立对象一样使用它们。
组合模式建议使用一个通用接口来与产品和盒子
进行交互, 并且在该接口中声明一个计算总价的方法。
该方式的最大优点在于你无需了解构成树状结构的对象的具体类。
例子:比如一个集团公司,他有一个母公司,下设很多家子公司。不管是母公司或者子公司,都有各自的财务部,人力部等。对于母公司来说,不论是子公司,还是直属的财务部,人力部等,都是他的部门。
class Company{
public:
Company(string name){
m_name = name;}
virtual ~Company(){
}
virtual void Add(Company *pCom){
}
virtual void Show(int depth){
}
protected:
string m_name;
};
// 具体的公司
class ConcreteCompany: public Company{
public:
ConcreteCompany(string name): Company(name){
}
virtual ~ConcreteCompany(){
}
void Add(Company *pCon){
m_listCompany.push_back(pCom);}
void Show(int depth){
for(int i = 0; i < depth; i++)
cout << "-";
cout << m_name<<endl;
list<Company*>::iternator iter = m_listCompany.begin();
for(; iter != m_listCompany.end(); iter++)
(*iter)->Show(depth+2);
}
private:
list<Company*> m_listCompany;
};
//具体的部门
class FinaneDepartment: public Company{
public:
FinanceDepartment(string name): Company(name){
}
vitrual ~FinanceDepartment(){
}
virtual void Show(int depth){
for(int i = 0; i < depth; i++)
cout << "-";
cout << m_name << endl;
}
};
class HRDepartment: public Compnay{
public:
HRDepartment(string name): Company(name){
}
vitrual ~HRDepartment(){
}
virtual void Show(int depth){
for(int i = 0; i < depth; i++)
cout << "-";
cout << m_name << endl;
}
}
优点:
装饰模式是一种结构型设计模式, 允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。
例如:一个手机,允许为他添加特性,比如增加挂件,手机贴膜等。一种灵活的设计方式是,将手机嵌入到另一个对象中,有这个对象完成特性的添加,我们将这个嵌入的对象为装饰。
class Phone{
public:
Phone(){
}
virutal ~Phone(){
}
virutal void ShowDecorate(){
}
};
class iPhone: public Phone{
private:
string m_name;
public:
iPhome(String name): m_name(name){
}
~iPhone(){
}
void ShowDecorate(){
cout << m_name << "的装饰" << endl;}
};
class NokiaPhone: public Phone{
private:
string m_name;
public:
NokiaPhone(string name): m_name(name){
}
~NokiaName(){
}
void ShowDecorate(){
cout << m_name<< "的装饰" << endl;}
};
// 装饰类
class DecoratorPhone: public Phone{
private:
Phone *m_phone;
public:
DecoratorPhone(Phone *phone): m_phone(phone){
}
virtual void ShowDecorate(){
m_phone->ShowDecorate();}
};
class DecoratorPhoneA: public DecoratorPhone{
public:
DecoratorPhoneA(Phone *phone): DecoratorPhone(phone){
}
void ShowDecorate(){
DecoratorPhone::ShowDecorate(); AddDecorate();}
private:
void AddDecorate(){
cout << "增加挂件" << endl;}
};
class DecoratePhoneB: public DecoratorPhone{
public:
DecoratorPhoneB(Phone *phone): DecoratorPhone(phone){
}
void ShowDecorate(){
DecoratorPhone::ShowDecorate(); AddDecorate();}
private:
void AddDecorate(){
cout << "屏幕贴膜" << endl;}
};
int main(){
shared_ptr<Phone> phone1(new NokiaPhone("6300"));
shared_ptr<Phone> dpa(new DecoratorPhoneA(phone1)); // 装饰,增加挂件
shared_ptr<Phone> dpb(new DecoratorPhoneB(dpa)); // 装饰,屏幕贴膜
dpb->ShowDecorate();
return 0;
}
优点:
缺点:
外观模式是一种结构性设计模式,能为程序库、框架或者其他复杂类提供一个简单的接口。
外观类为包含许多活动部件的复杂子系统提供一个简单的接口。与直接调用子系统相比,外观提供的功能可能比较有限,但它却包含了客户端真正关心的功能。
如果你的程序需要与包含几十种功能的复杂库整合, 但只需使用其中非常少的功能, 那么使用外观模式会非常方便。
例子:编译器需要经过4个步骤:词法分析,语法分析,中间代码生成,机器码生成。对于这个系统就可以使用外观模式。
class Sacnner{
public:
void Scan(){
cout << "词法分析" << endl;}
};
class Parser{
public:
void Parse(){
cout << "语法分析" << endl;}
};
class GenMidCode{
public:
void GenCode(){
cout << "中间代码生成" << endl;}
};
class GenMachineCode{
public:
void GenCode(){
cout << "机器码生成" << endl;}
};
class Compile{
public:
void Run(){
Scanner scanner;
Parser parser;
GenMidCode genMidCode;
GenMachineCode genMachineCode;
scanner.Scan();
parser.Parse();
genMidCode.GenCode();
genMachineCode.GenCode();
}
};
优点:
缺点:
享元模式是一种结构型设计模式, 它摒弃了在每个对象中保存所有数据的方式, 通过共享多个对象所共有的相同状态, 让你能在有限的内存容量中载入更多对象。
对象的常量数据通常被称为内在状态,其位于对象中,其他对象只能读取但不能修改其数值。而数值的其他状态常常能被其他对象“从外部”改变,因此被称为外在状态。
享元模式建议不在对象中存储外在状态, 而是将其传递给依赖于它的一个特殊方法。 程序只在对象中保存内在状态, 以方便在不同情景下重用。 这些对象的区别仅在于其内在状态 (与外在状态相比, 内在状态的变体要少很多), 因此你所需的对象数量会大大削减。
将仅存储内在状态的对象称为享元。
外在状态在大部分情况下,都会被移动到容器对象中,也就是我们应用享元模式前的聚合对象中。
为了能更方便的访问各种享元,可以创建一个工厂方法来管理已有享元对象的缓存池。
例子:以树为例
class TreeType{
private:
string m_name;
string m_color;
string m_texture;
public:
TreeType(string name, string color, string texture): m_name(name), m_color(color), m_texture(texture){
cout << "construct with " << name << " " << color << " " << texture << endl;
}
void draw(int x, int y){
cout<< "TreeType Draw at (" << x << "," << y << ")" << endl;
}
};
class TreeFactory{
public:
map<string, TreeType> treeTypes;
TreeType getTreeType(string name, string color, string texture){
map<string, TreeType>::iterator typeIter = treeTypes.find(name + color + texture);
if(typeIter == treeTypes.end()){
TreeType type(name, color, texture);
treeTypes.insert(make_pair(name+color+texture, type));
return type;
}
return typeIter->second;
}
};
class Tree{
private:
int x, y;
TreeType type;
public:
Tree(int _x, int _y, TreeType _type) : x(_x), y(_y), type(_type){
}
void draw(){
type.draw(x, y);
}
};
void plantTrees(int x, int y, string name, string color, string texture, TreeFactory& treeFactory, vector<Tree>& trees){
TreeType type = treeFactory.getTreeType(name, color, texture);
Tree tree(x, y, type);
trees.push_back(tree);
}
优点:
缺点:
代理模式是一种结构型设计模式, 让你能够提供对象的替代品或其占位符。 代理控制着对于原对象的访问, 并允许在将请求提交给对象前后进行一些处理。
代理模式建议新建一个与原服务对象接口相同的代理类,然后更新应用将代理对象传递给素有原始对象客户端。代理类收到客户端请求后会创建实际的服务对象,并将所有工作委派给他。
比如代理将自己伪装成数据库对象,可以在客户端或者实际数据库对象不知情的情况下处理延迟初始化和缓存查询结果的工作。
例如:一个可以在文档中嵌入图形对象的文档编辑器。有些图形的创建开销很大,因此可以创建一个图像代理,先不打开图形,需要打开的时候再打开
class Image{
public:
Image(string name) : m_imageName(name){
}
virtual ~Image(){
}
virtual void Show(){
}
protected:
string m_imageName;
};
class BigImage: public Image{
public:
BigImage(string name): Image(name){
}
~BigImage(){
}
void Show(){
cout << "Show Big Image" << m_imageName << endl;}
};
class BigImageProxy: public Image{
private:
BigImage *m_bigImage;
public:
BigImageProxy(string name) : Image(name), m_bigImage(0){
}
~BigImageProxy(){
delete m_bigImage;}
void Show(){
if(m_bigImage == NULL)
m_bigImage = new BigImage(m_imageName);
m_bigImage->Show();
}
}
int main(){
Image *image = new BigImageProxy("proxy.jpg");
image->Show();
delete image;
return 0;
}
责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。
与许多其他行为设计模式一样, 责任链会将特定行为转换为被称作处理者的独立对象。
模式建议你将这些处理者连成一条链。 链上的每个处理者都有一个成员变量来保存对于下一处理者的引用。 除了处理请求外, 处理者还负责沿着链传递请求。 请求会在链上移动, 直至所有处理者都有机会对其进行处理。
处理者可以决定不再沿着链传递请求, 这可高效地取消所有后续处理步骤。
例如:员工要求加薪,需要一层一层批准
class Manager{
protected:
Manager *m_manager;
string m_name;
public:
Manager(Manager *manager, string name): m_manager(manager), m_name(name){
}
virtual void DealWithRequest(string name, int num){
}
};
class CommonManager: public Manager{
public:
CommonManager(Manager *manager, string name): Manager(manager, name){
}
void DealWithRequest(string name, int num){
if(num < 500)
cout << "commonmanager " << name << " accept " << "raises $" << num << endl;
else{
cout << "commonmanager cannot deal" << endl;
m_manager->DealWithRequest(name, num);
}
}
};
class MajorManager: public Manager{
public:
MajorManager(Manager *manager, string name): Manager(manager, name){
}
void DealWithRequest(string name, int num){
if(num < 1000)
cout << "majormanager " << name << " accept " << "raises $" << num << endl;
else{
cout << "majormanager cannot deal" << endl;
m_manager->DealWithRequest(name, num);
}
}
};
class GeneralManager: public Manager{
public:
GeneralManager(Manager *manager, string name): Manager(manager, name){
}
void DealWithRequest(string name, int num){
cout << "generalmanager " << name << " accept " << "raises $" << num << endl;
}
};
int main(){
Manager *general = new GeneralManager(NULL, "A");
Manager *major = new MajorManager(general, "B");
Manager *common = new CommonManager(major, "C");
common->DealWithRequest("D", 300);
common->DealWithRequest("E", 1000);
delete general;
delete major;
delete common;
return 0;
}
优点:
缺点:
中介者模式是一种行为设计模式, 能让你减少对象之间混乱无序的依赖关系。 该模式会限制对象之间的直接交互, 迫使它们通过一个中介者对象进行合作。
中介者模式建议你停止组件之间的直接交流并使其相互独立。 这些组件必须调用特殊的中介者对象, 通过中介者对象重定向调用行为, 以间接的方式进行合作。 最终, 组件仅依赖于一个中介者类, 无需与多个其他组件相耦合。
采用这种方式, 中介者模式让你能在单个中介者对象中封装多个对象间的复杂关系网。 类所拥有的依赖关系越少, 就越易于修改、 扩展或复用。
例如:租房为例,如果没有房屋中介,那么房客要自己找房东,房东要自己找房客。
class Mediator;
class Person{
portected:
Mediator *m_mediator;
public:
virtual void SetMediator(Mediator *mediator){
}
virtual void SendMessage(string msg){
}
virtual void GetMessage(string msg){
}
};
class Mediator{
public:
virtual void Send(string msg, Person *person){
}
virtual void SetA(Person *A){
}
virtual void SetB(Person *B){
}
};
class Renter: public Person{
public:
void SetMediator(Mediator *mediator){
m_mediator = mediator;}
void SendMessage(string msg){
m_mediator->Send(msg, this);}
void GetMessage(string msg){
cout << "renter get msg" << endl;}
};
class Landlord: public Person{
public:
void SetMediator(Mediator *mediator){
m_mediator = mediator;}
void SendMessage(string msg){
m_mediator->Send(msg, this);}
void GetMessage(string msg){
cout << "landlord get msg" << endl;}
};
class HouseMediator: public Mediator{
private:
Person *m_A;
Person *m_B;
public:
HouseMediator(): m_A(NULL), m_B(NULL){
}
void SetA(Person *A){
m_A = A;}
void SetB(Person *B){
m_B = B;}
void Send(string msg, Person *person){
if(person == m_A)
m_B->GetMessage(msg);
else
m_A->GetMessage(msg);
}
};
优点:
缺点:
观察者模式是一种行为设计模式, 允许你定义一种订阅机制, 可在对象事件发生时通知多个 “观察” 该对象的其他对象。
拥有一些值得关注的状态的对象通常被称为目标, 由于它要将自身的状态改变通知给其他对象, 我们也将其称为发布者 (publisher)。 所有希望关注发布者状态变化的其他对象被称为订阅者 (subscribers)。
观察者模式建议为发布者类添加订阅机制,让每个对象都能订阅或者取消订阅发布者消息流。
实际上,该机制包括:1,一个用于存储订阅者对象引用的列表成员变量;2,几个用于添加或者删除该列表中订阅者的公有方法。
update
方法。例如:博主和读者的问题
class Observer{
public:
Observer(){
}
virtual ~Observer(){
}
virutal void Update(){
}
};
class Blog{
public:
Blog(){
}
~Blog(){
}
void Attach(Observer *observer){
m_observers.push_back(observer);}
void Remove(Observer *observer){
m_observers.remove(observer);}
void Notify(){
list<Observer*>::iterator iter = m_observers.begin();
for(; iter != m_observers.end(); iter++)
(*iter)->Update();
}
virtual void SetStatus(string s){
m_status = s;}
virtual string GetStatus(){
return m_status;}
private:
list<Observer*> m_observers;
protected:
stdring m_status;
};
class BlogCSDN: public Blog{
private:
string m_name;
public:
BlogCSDN(string name): m_name(name){
}
~BlogCSDN(){
}
void SetStatus(string s){
m_status="CSDN message: "+m_name+s;}
string GetStatus(){
return m_status;}
};
class ObserverBlog: public Observer{
private:
string m_name;
Blog *m_blog;
public:
ObserverBlog(string name, Bolg *blog): m_name(name), m_blog(blog){
}
~ObserverBolg(){
}
void Update(){
string status = m_blog->GetStatus();
cout << m_name << "--------" << status << endl;
}
};
优点:
缺点:
迭代器模式是一种行为设计模式,让你能在不暴露集合底层表现形式(列表、栈和树等)的情况下遍历集合中所有的元素。
迭代器模式的主要思想就是将集合的遍历行为抽取为单独的迭代器模式。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D1WayPxn-1602222462333)(C:/Users/free/Desktop/面试/interviewmd/assets/post/others/iterator.png)]
缺点: