设计模式

面向对象编程的核心思想–高内聚低耦合。
设计模式的大部分作用就是解耦,解耦的基本方式是将功能和逻辑分离。

设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理地运用设计模式可以完美地解决很多问题,每种模式在现实中都有相应的原理来与之对应,每种模式都描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是设计模式能被广泛应用的原因。

6种设计原则

单一职责原则

单一职责原则的英文名称是Single Responsibility Principle,简称是SRP。这个原则存在争议之处在于对职责的定义,什么是类的职责,以及怎么划分类的职责。

单一职责原则的好处:
1.类的复杂性降低,实现什么职责都有清晰明确的定义;
2.可读性提高,复杂性降低,那当然可读性提高了;
3.可维护性提高,可读性提高,那当然更容易维护了;
4.变更引起的风险降低,变更是必不可少的,如果接口的单一职责做得好,一个接口修改只对相应的实现类有影响,对其他的接口无影响,这对系统的扩展性、维护性都有非常大的帮助。

注意 单一职责原则提出了一个编写程序的标准,用“职责”或“变化原因”来衡量接口或类设计得是否优良,但是“职责”和“变化原因”都是不可度量的,因项目而异,因环境而异。

对于单一职责原则,我的建议是接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化。

里氏替换原则

里氏替换原则(Liskov Substitution Principle,LSP)有两个定义。

第一种定义,也是最正宗的定义:
If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T,the behavior of P is unchanged when o1 is substituted for >o2 then S is a subtype of T.

如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型S是类型T的子类型。


第二种定义:
Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

所有引用基类的地方必须能透明地使用其子类的对象。

第二个定义是最清晰明确的,通俗点讲,只要父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误或异常,使用者可能根本就不需要知道是父类还是子类。但是,反过来就不行了,有子类出现的地方,父类未必就能适应。

注意 如果子类不能完整地实现父类的方法,或者父类的某些方法在子类中已经发生“畸变”,则建议断开父子继承关系,采用依赖、聚集、组合等关系代替继承。

依赖倒置原则

概念
依赖倒置原则(Dependence Inversion Principle,DIP)

High level modules should not depend upon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details.Details should depend upon abstractions.

翻译过来,包含三层含义:
1.高层模块不应该依赖低层模块,两者都应该依赖其抽象;
2.抽象不应该依赖细节;
3.细节应该依赖抽象。

依赖倒置原则在Java语言中的表现就是:
● 模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的;
● 接口或抽象类不依赖于实现类;
● 实现类依赖接口或抽象类。

更加精简的定义就是“面向接口编程”——OOD(Object-Oriented Design,面向对象设计)的精髓之一。

依赖倒置原则的优点:
依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和可维护性。
减少并行开发引起的风险。

依赖的三种写法
1.构造函数传递依赖对象;
2.Setter方法传递依赖对象;
3.接口声明依赖对象。

规则
1.每个类尽量都有接口或抽象类,或者抽象类和接口两者都具备。
2.变量的表面类型尽量是接口或者是抽象类。
3.任何类都不应该从具体类派生。
4.尽量不要覆写基类的方法。
5.结合里氏替换原则使用。

接口隔离原则

接口:
实例接口(Object Interface)和类接口(Class Interface)。
隔离:
Clients should not be forced to depend upon interfaces that they don’t use.
客户端不应该依赖它不需要的接口。
The dependency of one class to another one should depend on the smallest possible interface.
类间的依赖关系应该建立在最小的接口上。

在实践中可以根据以下几个规则来衡量:
● 一个接口只服务于一个子模块或业务逻辑;
● 通过业务逻辑压缩接口中的public方法,接口时常去回顾,尽量让接口达到“满身筋骨肉”,而不是“肥嘟嘟”的一大堆方法;
● 已经被污染了的接口,尽量去修改,若变更的风险较大,则采用适配器模式进行转化处理;
● 了解环境,拒绝盲从。每个项目或产品都有特定的环境因素,别看到大师是这样做的你就照抄。千万别,环境不同,接口拆分的标准就不同。深入了解业务逻辑,最好的接口设计就出自你的手中!

迪米特法则

迪米特法则(Law of Demeter,LoD)也称为最少知识原则(Least Knowledge Principle,LKP),虽然名字不同,但描述的是同一个规则:一个对象应该对其他对象有最少的了解。通俗地讲,一个类应该对自己需要耦合或调用的类知道得最少,你(被耦合或调用的类)的内部是如何复杂都和我没关系,那是你的事情,我就知道你提供的这么多public方法,我就调用这么多,其他的我一概不关心。

迪米特法则要求类“羞涩”一点,尽量不要对外公布太多的public方法和非静态的public变量,尽量内敛,多使用private、package-private、protected等访问权限。

一个类公开的public属性或方法越多,修改时涉及的面也就越大,变更引起的风险扩散也就越大。因此,为了保持朋友类间的距离,在设计时需要反复衡量:是否还可以再减少public方法和属性,是否可以修改为private、package-private(包类型,在类、方法、变量前不加访问权限,则默认为包类型)、protected等访问权限,是否可以加上final关键字等。

总之,高内聚低耦合,一个类应该减少对外公开的接口,做到即使改变也不会影响其他类。

开闭原则

Software entities like classes,modules and functions should be open for extension but closed for modifications.

一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。

开闭原则对扩展开放,对修改关闭,并不意味着不做任何修改,低层模块的变更,必然要有高层模块进行耦合,否则就是一个孤立无意义的代码片段。
cdq:通过覆写来实现新功能,而不是修改。
通过扩展来实现业务逻辑的变化,而不是修改。

23种设计模式归类

创建型模式

这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。

-工厂方法模式(Factory Method Pattern)★★★★★
-抽象工厂模式(Abstract Factory Pattern)★★★★★
-单例模式(Singleton Pattern)★★★★☆
-建造者模式(Builder Pattern)★★☆☆☆
-原型模式(Prototype Pattern)★★★☆☆

结构型模式

这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。

-适配器模式(Adapter Pattern)★★★★☆
-桥接模式(Bridge Pattern)★★★☆☆
-过滤器模式(Filter、Criteria Pattern)
-组合模式(Composite Pattern)★★★★☆
-装饰器模式(Decorator Pattern)★★★☆☆
-外观模式(Facade Pattern)★★★★★
-享元模式(Flyweight Pattern)★☆☆☆☆
-代理模式(Proxy Pattern)★★★★☆

行为型模式

这些设计模式特别关注对象之间的通信。

-责任链模式(Chain of Responsibility Pattern)★★☆☆☆
-命令模式(Command Pattern)★★★★☆
-解释器模式(Interpreter Pattern)★☆☆☆☆
-迭代器模式(Iterator Pattern)★★★★★
-中介者模式(Mediator Pattern)★★☆☆☆
-备忘录模式(Memento Pattern)★★☆☆☆
-观察者模式(Observer Pattern)★★★★★
-状态模式(State Pattern)★★★☆☆
-空对象模式(Null Object Pattern)
-策略模式(Strategy Pattern)★★★★☆
-模板模式(Template Pattern)★★★☆☆
-访问者模式(Visitor Pattern)★☆☆☆☆

J2EE 模式

这些设计模式特别关注表示层。这些模式是由 Sun Java Center 鉴定的。

-MVC 模式(MVC Pattern)
-业务代表模式(Business Delegate Pattern)
-组合实体模式(Composite Entity Pattern)
-数据访问对象模式(Data Access Object Pattern)
-前端控制器模式(Front Controller Pattern)
-拦截过滤器模式(Intercepting Filter Pattern)
-服务定位器模式(Service Locator Pattern)
-传输对象模式(Transfer Object Pattern)

23种设计模式解析

单例模式

Ensure a class has only one instance, and provide a global point of access to it.

确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

Singleton类称为单例类,通过使用private的构造函数确保了在一个应用中只产生一个实例,并且是自行实例化的。

应用案例:总线模式。


```cpp #include

class Singleton
{
public:
~Singleton(){
std::cout<<”destructor called!”<<std::endl;
}
Singleton(const Singleton&)=delete;
Singleton& operator=(const Singleton&)=delete;
static Singleton& get_instance(){
static Singleton instance;
return instance;

}

private:
Singleton(){
std::cout<<”constructor called!”<<std::endl;
}
};

int main(int argc, char *argv[])
{
Singleton& instance_1 = Singleton::get_instance();
Singleton& instance_2 = Singleton::get_instance();
return 0;
}

constructor called!
destructor called!


## 为什么要用工厂模式?
想想我们为什么要用工厂模式?下面我就简单举例子:
文件IO的操作我们会经常用得到吧,所以BufferedReader对象经常要创建的:
```cpp
// 创建一个BufferedReader对象
File file = new File("aa.txt");
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);

可以看出来,创建一个BufferReader对象里面需要一个FileReader对象,而FileReader对象又要File对象。那创建这个BufferReader对象还是比较麻烦的(代码上看不麻烦,从构造上看还是挺麻烦的)!

虽然比较麻烦,但我们还能用,能用就行!于是乎,我们就去写代码了,现在有三个类都要进行文件的读写操作,于是他们就有这样的代码:

public class FileOperateA {

    public static void main(String[] args) throws FileNotFoundException {
        File file = new File("aa.txt");
        FileReader fileReader = new FileReader(file);
        BufferedReader bufferedReader = new BufferedReader(fileReader);


        // 读写文件....
    }
}

此时:上头说,我要换成LineNumberReader来读写,有这个需求!那我们作为一个写代码的,能怎么办?很绝望也需要去完成呀。

  • 不熟悉IDE的小伙子就一个一个将BufferedReader改成LineNumberReader,现在就3个类用到了BufferedReader,也就改6次而已。(ps:那如果很多地方都用到了呢?)
  • 熟悉IDE的小伙子就全局替换重构,妥妥的!

那有没有一种方法能够让创建对象变得简单而且修改对象时能很方便呢?
工厂模式就行了。

再说从面向对象的角度来看:我一个操作文件的类还要我会创建BufferReader是不是有点过分了?(职责没有分工好)
交给工厂来创建对象这就很面向对象了!

首先我们创建一个工厂类,它可以生产Reader对象!

// 创建Reader对象的工厂
public class ReaderFactory {
    public static Reader getReader() throws FileNotFoundException {
        File file = new File("aa.txt");
        FileReader fileReader = new FileReader(file);
        BufferedReader reader = new BufferedReader(fileReader);
        return reader;
    }
}

那么我们要得到BufferReader对象就贼简单了:

public class FileOperateA {

    public static void main(String[] args) throws FileNotFoundException {


        //-------我有工厂了,还用自己搞吗?不用了!
        //File file = new File("aa.txt");
        //FileReader fileReader = new FileReader(file);
        //BufferedReader bufferedReader = new BufferedReader(fileReader);
        //-------我有工厂了,还用自己搞吗?不用了!

        // 用工厂来创建出对象
        Reader reader = ReaderFactory.getReader();

        // 读写文件....
    }
}

工厂将我们创建的对象过程给屏蔽了!

此时我要改成LineNumberReader怎么玩?在工厂上改一下就好了.

工厂方法模式

Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses.

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。


main(),女娲

IHuman,产品接口

CYellowHuman,产品之一

CWhiteHuman,产品之二

CBlackHuman,产品之三

IHumanFactory,工厂接口

CYellowHumanFactory,工厂之一

CWhiteHumanFactory,工厂之二

CBlackHumanFactory,工厂之三

女娲造人图

IHuman.h

#pragma once
class IHuman
{
public:
    IHuman(void)
    {
    }
    virtual ~IHuman(void)
    {
    }
    virtual void Laugh() = 0;
    virtual void Cry() = 0;
    virtual void Talk() = 0;
};

YellowHuman.h

#pragma once
#include "ihuman.h"
class CYellowHuman :
    public IHuman
{
public:
    CYellowHuman(void);
    ~CYellowHuman(void);
    void Laugh();
    void Cry();
    void Talk();
};

YellowHuman.cpp

#include <stdio.h>
#include "YellowHuman.h"
#include <iostream>
using std::cout;
using std::endl;
CYellowHuman::CYellowHuman(void)
{
}
CYellowHuman::~CYellowHuman(void)
{
}
void CYellowHuman::Cry()
{
    cout << "黄色人种会哭" << endl;
}
void CYellowHuman::Laugh()
{
    cout << "黄色人种会大笑,幸福呀!" << endl;
}
void CYellowHuman::Talk()
{
    cout << "黄色人种会说话,一般说的都是双字节" << endl;
}

//WhiteHuman.h

#pragma once
#include "ihuman.h"
class CWhiteHuman :
    public IHuman
{
public:
    CWhiteHuman(void);
    ~CWhiteHuman(void);
    void Laugh();
    void Cry();
    void Talk();
};

//WhiteHuman.cpp

#include <stdio.h>
#include "WhiteHuman.h"
#include <iostream>
using std::cout;
using std::endl;
CWhiteHuman::CWhiteHuman(void)
{
}
CWhiteHuman::~CWhiteHuman(void)
{
}
void CWhiteHuman::Cry()
{
    cout << "白色人种会哭" << endl;
}
void CWhiteHuman::Laugh()
{
    cout << "白色人种会大笑,侵略的笑声" << endl;
}
void CWhiteHuman::Talk()
{
    cout << "白色人种会说话,一般都是单字节" << endl;
}

BlackHuman.h

#pragma once
#include "ihuman.h"
class CBlackHuman :
    public IHuman
{
public:
    CBlackHuman(void);
    ~CBlackHuman(void);
    void Laugh();
    void Cry();
    void Talk();
};

BlackHuman.cpp

#include <stdio.h>
#include "BlackHuman.h"
#include <iostream>
using std::cout;
using std::endl;
CBlackHuman::CBlackHuman(void)
{
}
CBlackHuman::~CBlackHuman(void)
{
}
void CBlackHuman::Cry()
{
    cout << "黑人会哭" << endl;
}
void CBlackHuman::Laugh()
{
    cout << "黑人会笑" << endl;
}
void CBlackHuman::Talk()
{
    cout << "黑人可以说话,一般人听不懂" << endl;
}

IHumanFactory.h

#pragma once
#include "IHuman.h"
class IHumanFactory
{
public:
    IHumanFactory(void)
    {
    }
    virtual ~IHumanFactory(void)
    {
    }
    virtual IHuman * CreateHuman() = 0;
};

YellowHumanFactory.h

#pragma once
#include "ihumanfactory.h"
class CYellowHumanFactory :
    public IHumanFactory
{
public:
    CYellowHumanFactory(void);
    ~CYellowHumanFactory(void);
    virtual IHuman * CreateHuman(void);
};

YellowHumanFactory.cpp

#include <stdio.h>
#include "YellowHumanFactory.h"
#include "YellowHuman.h"
CYellowHumanFactory::CYellowHumanFactory(void)
{
}
CYellowHumanFactory::~CYellowHumanFactory(void)
{
}
IHuman * CYellowHumanFactory::CreateHuman( void )
{
    return new CYellowHuman();
}

//WhiteHumanFactory.h

#pragma once
#include "ihumanfactory.h"
class CWhiteHumanFactory :
    public IHumanFactory
{
public:
    CWhiteHumanFactory(void);
    ~CWhiteHumanFactory(void);
    virtual IHuman * CreateHuman(void);
};

//WhiteHumanFactory.cpp

#include <stdio.h>
#include "WhiteHumanFactory.h"
#include "WhiteHuman.h"
CWhiteHumanFactory::CWhiteHumanFactory(void)
{
}
CWhiteHumanFactory::~CWhiteHumanFactory(void)
{
}
IHuman * CWhiteHumanFactory::CreateHuman( void )
{
    return new CWhiteHuman();
}

BlackHumanFactory.h

#pragma once
#include "ihumanfactory.h"
class CBlackHumanFactory :
    public IHumanFactory
{
public:
    CBlackHumanFactory(void);
    ~CBlackHumanFactory(void);
    virtual IHuman * CreateHuman();
};

BlackHumanFactory.cpp

#include <stdio.h>
#include "BlackHumanFactory.h"
#include "BlackHuman.h"
CBlackHumanFactory::CBlackHumanFactory(void)
{
}
CBlackHumanFactory::~CBlackHumanFactory(void)
{
}
IHuman * CBlackHumanFactory::CreateHuman()
{
    return new CBlackHuman();
}

NvWa.cpp

#include <stdio.h>
#include "IHuman.h"
#include "YellowHuman.h"
#include "WhiteHuman.h"
#include "BlackHuman.h"
#include "IHumanFactory.h"
#include "YellowHumanFactory.h"
#include "WhiteHumanFactory.h"
#include "BlackHumanFactory.h"
#include <iostream>
using std::cout;
using std::endl;
using std::string;
void DoFactoryMethod1()
{
    cout << "----------第一批人是这样的:黄种人工厂来生产黄种人" << endl;
    IHumanFactory *pHumanFactory = new CYellowHumanFactory();
    IHuman *pHuman = pHumanFactory->CreateHuman();
    pHuman->Cry();
    pHuman->Laugh();
    pHuman->Talk();
    delete pHuman;
    delete pHumanFactory;
}
void DoFactoryMethod2()
{
    cout << "----------第二批人是这样的:白种人工厂来生产白种人" << endl;
    IHumanFactory *pHumanFactory = new CWhiteHumanFactory();
    IHuman *pHuman = pHumanFactory->CreateHuman();
    pHuman->Cry();
    pHuman->Laugh();
    pHuman->Talk();
    delete pHuman;
    delete pHumanFactory;
}
void DoFactoryMethod3()
{
    cout << "----------第三批人是这样的:黑种人工厂来生产黑种人" << endl;
    IHumanFactory *pHumanFactory = new CBlackHumanFactory();
    IHuman *pHuman = pHumanFactory->CreateHuman();
    pHuman->Cry();
    pHuman->Laugh();
    pHuman->Talk();
    delete pHuman;
    delete pHumanFactory;
}
int main()
{
    //工厂方法
    cout << "----------工厂方法:" << endl;
    DoFactoryMethod1();
    DoFactoryMethod2();
    DoFactoryMethod3();

    _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
    _CrtDumpMemoryLeaks();
    return 0;
}
----------工厂方法:
----------第一批人是这样的:黄种人工厂来生产黄种人
黄色人种会哭
黄色人种会大笑,幸福呀!
黄色人种会说话,一般说的都是双字节
----------第二批人是这样的:白种人工厂来生产白种人
白色人种会哭
白色人种会大笑,侵略的笑声
白色人种会说话,一般都是单字节
----------第三批人是这样的:黑种人工厂来生产黑种人
黑人会哭
黑人会笑
黑人可以说话,一般人听不懂 

抽象工厂模式

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们的具体类。

抽象工厂,提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。对于工厂方法来说,抽象工厂可实现一系列产品的生产,抽象工厂更注重产品的组合。


main(),女娲

IHuman,产品接口

CYellowHuman,抽象产品之一

CYellowFemaleHuman,具体产品之一

CYellowMaleHuman,具体产品之二

CWhiteHuman,抽象产品之二

CWhiteFemaleHuman,具体产品之三

CWhiteMaleHuman,具体产品之四

CBlackHuman,抽象产品之三

CBlackFemaleHuman,具体产品之五

CBlackMaleHuman,具体产品之六

IHumanFactory,抽象工厂

CStandardHumanFactory,抽象工厂基类(此类可有可无)

CFemaleHumanFactory,工厂之一

CMaleHumanFactory,工厂之二

女娲造人新图

IHuman.h

#pragma once
class IHuman
{
public:

    IHuman(void)
    {
    }

    virtual ~IHuman(void)
    {
    }

    virtual void Laugh() = 0;
    virtual void Cry() = 0;
    virtual void Talk() = 0;
    virtual void Sex() = 0;
};

YellowHuman.h

#pragma once
#include "ihuman.h"
#include <iostream>
using std::cout;
using std::endl;
class CYellowHuman :
    public IHuman
{
public:
    CYellowHuman(void)
    {
    }
    ~CYellowHuman(void)
    {
    }
    void Laugh()
    {
        cout << "黄色人种会大笑,幸福呀!" << endl;
    }
    void Cry()
    {
        cout << "黄色人种会哭" << endl;
    }
    void Talk()
    {
        cout << "黄色人种会说话,一般说的都是双字节" << endl;
    }
    virtual void Sex() = 0;
};

YellowFemaleHuman.h

#pragma once
#include "yellowhuman.h"
#include <iostream>
using std::cout;
using std::endl;
class CYellowFemaleHuman :
    public CYellowHuman
{
public:
    CYellowFemaleHuman(void)
    {
    }
    ~CYellowFemaleHuman(void)
    {
    }
    void Sex()
    {
        cout << "该黄种人的性别为女..." << endl;
    }
};

YellowMaleHuman.h

#pragma once
#include "yellowhuman.h"
#include <iostream>
using std::cout;
using std::endl;
class CYellowMaleHuman :
    public CYellowHuman
{
public:
    CYellowMaleHuman(void)
    {
    }
    ~CYellowMaleHuman(void)
    {
    }
    void Sex()
    {
        cout << "该黄种人的性别为男..." << endl;
    }
};

//WhiteHuman.h

#pragma once
#include "ihuman.h"
#include <iostream>
using std::cout;
using std::endl;
class CWhiteHuman :
    public IHuman
{
public:
    CWhiteHuman(void)
    {
    }
    ~CWhiteHuman(void)
    {
    }
    void Laugh()
    {
        cout << "白色人种会大笑,侵略的笑声" << endl;
    }
    void Cry()
    {
        cout << "白色人种会哭" << endl;
    }
    void Talk()
    {
        cout << "白色人种会说话,一般都是单字节" << endl;
    }
    virtual void Sex() = 0;
};

//WhiteFemaleHuman.h

#pragma once
#include "whitehuman.h"
#include <iostream>
using std::cout;
using std::endl;
class CWhiteFemaleHuman :
    public CWhiteHuman
{
public:
    CWhiteFemaleHuman(void)
    {
    }
    ~CWhiteFemaleHuman(void)
    {
    }
    void Sex()
    {
        cout << "该白种人的性别为女..." << endl;
    }
};

//WhiteMaleHuman.h

#pragma once
#include "whitehuman.h"
#include <iostream>
using std::cout;
using std::endl;
class CWhiteMaleHuman :
    public CWhiteHuman
{
public:
    CWhiteMaleHuman(void)
    {
    }
    ~CWhiteMaleHuman(void)
    {
    }
    void Sex()
    {
        cout << "该白种人的性别为男..." << endl;
    }
};

BlackHuman.h

#pragma once
#include "ihuman.h"
#include <iostream>
using std::cout;
using std::endl;
class CBlackHuman :
    public IHuman
{
public:
    CBlackHuman(void)
    {
    }
    ~CBlackHuman(void)
    {
    }
    void Laugh()
    {
        cout << "黑人会笑" << endl;
    }
    void Cry()
    {
        cout << "黑人会哭" << endl;
    }
    void Talk()
    {
        cout << "黑人可以说话,一般人听不懂" << endl;
    }

    virtual void Sex() = 0;
};

BlackFemaleHuman.h

#pragma once
#include "blackhuman.h"
#include <iostream>
using std::cout;
using std::endl;
class CBlackFemaleHuman :
    public CBlackHuman
{
public:
    CBlackFemaleHuman(void)
    {
    }
    ~CBlackFemaleHuman(void)
    {
    }
    void Sex()
    {
        cout << "该黑种人的性别为女..." << endl;
    }
};

BlackMaleHuman.h

#pragma once
#include "blackhuman.h"
#include <iostream>
using std::cout;
using std::endl;
class CBlackMaleHuman :
    public CBlackHuman
{
public:
    CBlackMaleHuman(void)
    {
    }
    ~CBlackMaleHuman(void)
    {
    }
    void Sex()
    {
        cout << "该黑种人的性别为男..." << endl;
    }
};

IHumanFactory.h

#pragma once
#include "IHuman.h"
class IHumanFactory
{
public:
    IHumanFactory(void)
    {
    }
    virtual ~IHumanFactory(void)
    {
    }
    virtual IHuman * CreateYellowHuman() = 0;
    virtual IHuman * CreateWhiteHuman() = 0;
    virtual IHuman * CreateBlackHuman() = 0;
};

MaleHumanFactory.h

#pragma once

#include "StandardHumanFactory.h"
#include "IHumanFactory.h"
template<class T>
class CMaleHumanFactory :
   public IHumanFactory
{
public:
   CMaleHumanFactory(void)
   {
   }
   ~CMaleHumanFactory(void)
   {
   }
   IHuman* CreateYellowHuman()
   {
      return new T;
   }
   IHuman* CreateWhiteHuman()
   {
      return new T;
   }
   IHuman* CreateBlackHuman()
   {
      return new T;
   }
};

FemaleHumanFactory.h

#pragma once
#include "standardhumanfactory.h"
template<class T>
class CFemaleHumanFactory :
   public IHumanFactory
{
public:
   CFemaleHumanFactory(void)
   {
   }
   ~CFemaleHumanFactory(void)
   {
   }
   IHuman* CreateYellowHuman()
   {
      return new T;
   }
   IHuman* CreateWhiteHuman()
   {
      return new T;
   }
   IHuman* CreateBlackHuman()
   {
      return new T;
   }
};

AbstractFactory.cpp

#include <stdio.h>
#include "IHuman.h"
#include "IHumanFactory.h"
#include "FemaleHumanFactory.h"
#include "MaleHumanFactory.h"
#include "yellowhuman.h"
#include "YellowFemaleHuman.h"
#include "YellowMaleHuman.h"
#include "whitehuman.h"
#include "WhiteFemaleHuman.h"
#include "WhiteMaleHuman.h"
#include "blackhuman.h"
#include "BlackFemaleHuman.h"
#include "BlackMaleHuman.h"

void DoIt()
{
   IHumanFactory* pFemaleHumanFactory = new CFemaleHumanFactory<CYellowFemaleHuman>();
   IHuman* pYellowFemaleHuman = pFemaleHumanFactory->CreateYellowHuman();
   pYellowFemaleHuman->Cry();
   pYellowFemaleHuman->Laugh();
   pYellowFemaleHuman->Talk();
   pYellowFemaleHuman->Sex();
   delete pYellowFemaleHuman;
   delete pFemaleHumanFactory;

   IHumanFactory* pMaleHumanFactory = new CMaleHumanFactory<CYellowMaleHuman>();
   IHuman* pYellowMaleHuman = pMaleHumanFactory->CreateYellowHuman();
   pYellowMaleHuman->Cry();
   pYellowMaleHuman->Laugh();
   pYellowMaleHuman->Talk();
   pYellowMaleHuman->Sex();
   delete pYellowMaleHuman;
   delete pMaleHumanFactory;
}
int main()
{
   DoIt();
   _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
   _CrtDumpMemoryLeaks();
   return 0;
}
黄色人种会哭
黄色人种会大笑,幸福呀!
黄色人种会说话,一般说的都是双字节
该黄种人的性别为女...
黄色人种会哭
黄色人种会大笑,幸福呀!
黄色人种会说话,一般说的都是双字节
该黄种人的性别为男... 

模板方法模式

Define the skeleton of an algorithm in an operation,deferring some steps to subclasses.Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.

定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

main(),客户

CHummerModel,悍马模型

CHummerH1Model,悍马模型型号1

CHummerH2Model,悍马模型型号2

说明:在CHummerModel声明Start、Engineboom、Alarm、Stop虚函数,由派生类实现。基类的Run负责组织逻辑,分别调用这几个派生类实现的函数。

注意:基类中的Run应该禁止派生类覆盖。
悍马车模类图

HummerModel.h

#pragma once
class CHummerModel
{
public:
    CHummerModel(void);
    virtual ~CHummerModel(void);
    void Run();
protected:
    virtual void Start() = 0;
    virtual void Stop() = 0;
    virtual void Alarm() = 0;
    virtual void EngineBoom() = 0;
    virtual bool IsAlarm();
};

HummerModel.cpp

#include <stdio.h>
#include "HummerModel.h"
#include <iostream>
using std::cout;
using std::endl;
CHummerModel::CHummerModel(void)
{
}
CHummerModel::~CHummerModel(void)
{
}
void CHummerModel::Run()
{
    //先发动汽车
    Start();
    //引擎开始轰鸣
    EngineBoom();
    //然后就开始跑了,跑的过程中遇到一条狗挡路,就按喇叭
    if (IsAlarm())
        Alarm();

    //到达目的地就停车
    Stop();
}
bool CHummerModel::IsAlarm()
{
    //钩子方法,默认喇叭是会响的
    return true;
}

HummerH1Model.h

#pragma once
#include "hummermodel.h"
class CHummerH1Model :
    public CHummerModel
{
public:
    CHummerH1Model(void);
    ~CHummerH1Model(void);
    void SetAlarm(bool tag);
    void Start();
    void Stop();
    void Alarm();
    void EngineBoom();
    bool IsAlarm();
private:
    bool m_isAlarm;
};

HummerH1Model.cpp

#include <stdio.h>
#include "HummerH1Model.h"
#include <iostream>
using std::cout;
using std::endl;
CHummerH1Model::CHummerH1Model(void)
{
    m_isAlarm = true;
}
CHummerH1Model::~CHummerH1Model(void)
{
}
void CHummerH1Model::Start()
{
    cout << "悍马H1发动..." << endl;
}
void CHummerH1Model::Stop()
{
    cout << "悍马H1停车..." << endl;
}
void CHummerH1Model::Alarm()
{
    cout << "悍马H1鸣笛" << endl;
}
void CHummerH1Model::EngineBoom()
{
    cout << "悍马H1引擎声音是这样...." << endl;
}
bool CHummerH1Model::IsAlarm()
{
    return this->m_isAlarm;
}
void CHummerH1Model::SetAlarm( bool tag )
{
    this->m_isAlarm = tag;
}

HummerH2Model.h

#pragma once
#include "hummermodel.h"
class CHummerH2Model :
    public CHummerModel
{
public:
    CHummerH2Model(void);
    ~CHummerH2Model(void);
    void Start();
    void Stop();
    void Alarm();
    void EngineBoom();
    bool IsAlarm();
};

HummerH2Model.cpp

#include <stdio.h>
#include "HummerH2Model.h"
#include <iostream>
using std::cout;
using std::endl;
CHummerH2Model::CHummerH2Model(void)
{
}
CHummerH2Model::~CHummerH2Model(void)
{
}
void CHummerH2Model::Start()
{
    cout << "悍马H2发动..." << endl;
}
void CHummerH2Model::Stop()
{
    cout << "悍马H2停车..." << endl;
}
void CHummerH2Model::Alarm()
{
    cout << "悍马H2鸣笛" << endl;
}
void CHummerH2Model::EngineBoom()
{
    cout << "悍马H2引擎声音是这样...." << endl;
}
bool CHummerH2Model::IsAlarm()
{
    return false;
}

TemplateMethod.cpp

#include <stdio.h>
#include "HummerModel.h"
#include "HummerH1Model.h"
#include "HummerH2Model.h"
#include <crtdbg.h>
int main()
{
    //客户开着H1型号,出去遛弯了
    CHummerModel *ph1 = new CHummerH1Model();
    ph1->Run();
    delete ph1;

    //客户开H2型号,出去玩耍了
    CHummerModel *ph2 = new CHummerH2Model();
    ph2->Run();
    delete ph2;

    //客户开着H1型号,出去遛弯了,并且不让喇叭响
    CHummerH1Model *ph11 = new CHummerH1Model();
    ph11->SetAlarm(false);
    ph11->Run();
    delete ph11;

    _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
    _CrtDumpMemoryLeaks();
    return 0;
}
悍马H1发动...
悍马H1引擎声音是这样....
悍马H1鸣笛
悍马H1停车...悍马H2发动...悍马H2引擎声音是这样....
悍马H2停车...悍马H1发动...悍马H1引擎声音是这样....
悍马H1停车...

建造者模式

Separate the construction of a complex object from its representation so that the same construction process can create different representations.

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。


main(),客户

CCarModel,产品模型

CBenzModel,奔驰模型

CBMWModel,宝马模型

ICarBuilder,建造者接口

CBenzBuilder,奔驰建造者

CBMWBuilder,宝马建造者

CDirector,导演

说明:CCarModel实现模板方法,Builder负责开始建造产品。建造产品时,构建的顺序由Director或main决定。

注意:建造者模式和抽象工厂非常类似。建造者更重视产品建造时的逻辑顺序,而抽象工厂更重视生产出不同型号的产品,抽象工厂不关心顺序。

汽车模型类图

// Builder.cpp

#include <stdio.h>
#include "CarModel.h"
#include "BenzModel.h"
#include "BMWModel.h"
#include "BenzBuilder.h"
#include "BMWBuilder.h"
#include "Director.h"
#include <vector>
#include <iostream>
using std::vector;
using std::string;
using std::cout;
using std::endl;


void DoBenzRun()
{
   cout << "----------生成奔驰模型----------" << endl;
   CBenzModel* pBenz = new CBenzModel();
   vector<string> seq;
   seq.push_back("engine boom");//客户要求run的时候先发动引擎
   seq.push_back("start");//启动起来
   seq.push_back("stop");//开了一段就停下来

   pBenz->SetSequence(&seq);
   pBenz->Run();
   delete pBenz;
}

//使用模式后,由benzBuilder和bmwBuilder来生成,并且使用同样的创建顺序。
void DoBuilder()
{
   cout << "----------用同一个顺序,生成模型----------" << endl;
   vector<string> seq;
   seq.push_back("engine boom");
   seq.push_back("start");
   seq.push_back("stop");

   CBenzBuilder benzBuilder;
   benzBuilder.SetSequence(&seq);
   CBenzModel* pBenz = dynamic_cast<CBenzModel*>(benzBuilder.GetCarModel());
   pBenz->Run();

   CBMWBuilder bmwBuilder;
   bmwBuilder.SetSequence(&seq);
   CBMWModel* pBmw = dynamic_cast<CBMWModel*>(bmwBuilder.GetCarModel());
   pBenz->Run();
}
//使用指导者来封装创建的逻辑,把创建的顺序内聚在指导者类里面。
void DoDirector()
{
   cout << "----------批量生成模型----------" << endl;
   CDirector director;

   //1W辆A类型的奔驰车
   for (int i = 0; i < 2; i++)
      director.GetABenzModel()->Run();

   //100W辆B类型的奔驰车
   for (int i = 0; i < 2; i++)
      director.GetBBenzModel()->Run();

   //1000W辆C类型的宝马车
   for (int i = 0; i < 2; i++)
      director.GetCBMWModel()->Run();
}
int main()
{
   DoBenzRun();

   DoBuilder();

   DoDirector();

   _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
   _CrtDumpMemoryLeaks();
   return 0;
}

CarModel.h

#pragma once
#include <vector>
#include <iostream>
using std::vector;
using std::string;
class CCarModel
{
public:
    CCarModel(void);
    virtual ~CCarModel(void);
    void Run();
    void SetSequence(vector<string> *pSeq);
protected:
    virtual void Start() = 0;
    virtual void Stop() = 0;
    virtual void Alarm() = 0;
    virtual void EngineBoom() = 0;
private:
    vector<string> * m_pSequence;
};

CarModel.cpp

#include <stdio.h>
#include "CarModel.h"
#include <vector>
#include <iostream>
using std::vector;
using std::string;
CCarModel::CCarModel(void)
{
}
CCarModel::~CCarModel(void)
{
}
void CCarModel::SetSequence(vector<string> *pSeq)
{
    m_pSequence = pSeq;
}
void CCarModel::Run()
{
    vector<string>::const_iterator it = m_pSequence->begin();
    for (; it < m_pSequence->end(); ++it)
    {
        string actionName = *it;
        if(actionName.compare("start") == 0)
        {
            Start();
        }
        else if(actionName.compare("stop") == 0)
        {
            Stop();
        }
        else if(actionName.compare("alarm") == 0)
        {
            Alarm();
        }
        else if(actionName.compare("engine boom") == 0)
        {
            EngineBoom();
        }
    }
}

BenzModel.h

#pragma once
#include "carmodel.h"
class CBenzModel :
    public CCarModel
{
public:
    CBenzModel(void);
    ~CBenzModel(void);
protected:
    void Start();
    void Stop();
    void Alarm();
    void EngineBoom();
};

BenzModel.cpp

#include <stdio.h>
#include "BenzModel.h"
#include <iostream>
using std::cout;
using std::endl;
CBenzModel::CBenzModel()
{
}
CBenzModel::~CBenzModel()
{
}
void CBenzModel::Start()
{
   cout << "奔驰发动..." << endl;
}
void CBenzModel::Stop()
{
   cout << "奔驰停车..." << endl;
}
void CBenzModel::Alarm()
{
   cout << "奔驰鸣笛" << endl;
}
void CBenzModel::EngineBoom()
{
   cout << "奔驰引擎声音是这样...." << endl;
}

BMWModel.h

#pragma once
#include "carmodel.h"
class CBMWModel :
    public CCarModel
{
public:
    CBMWModel(void);
    ~CBMWModel(void);
protected:
    void Start();
    void Stop();
    void Alarm();
    void EngineBoom();
};

BMWModel.cpp

#include <stdio.h>
#include "BMWModel.h"
#include <iostream>
using std::cout;
using std::endl;
CBMWModel::CBMWModel(void)
{
}
CBMWModel::~CBMWModel(void)
{
}
void CBMWModel::Start()
{
    cout << "宝马发动..." << endl;
}
void CBMWModel::Stop()
{
    cout << "宝马停车..." << endl;
}
void CBMWModel::Alarm()
{
    cout << "宝马鸣笛" << endl;
}
void CBMWModel::EngineBoom()
{
    cout << "宝马引擎声音是这样...." << endl;
}

ICarBuilder.h

#pragma once
#include "CarModel.h"
#include <iostream>
#include <vector>
using std::string;
using std::vector;
class ICarBuilder
{
public:
    ICarBuilder(void)
    {
    }
    virtual ~ICarBuilder(void)
    {
    }
    virtual void SetSequence(vector<string> *pseq) = 0;
    virtual CCarModel * GetCarModel() = 0;
};

BenzBuilder.h

#pragma once
#include "icarbuilder.h"
#include "CarModel.h"
#include <iostream>
#include <vector>
using std::string;
using std::vector;
class CBenzBuilder :
    public ICarBuilder
{
public:
    CBenzBuilder(void);
    ~CBenzBuilder(void);
    void SetSequence(vector<string> *pSeq);
    CCarModel * GetCarModel();
private:
    CCarModel *m_pBenz;
};

BenzBuilder.cpp

#include <stdio.h>
#include "BenzBuilder.h"
#include "BenzModel.h"
CBenzBuilder::CBenzBuilder(void)
{
    m_pBenz = new CBenzModel();
}
CBenzBuilder::~CBenzBuilder(void)
{
    delete m_pBenz;
}
void CBenzBuilder::SetSequence(vector<string> *pSeq)
{
    m_pBenz->SetSequence(pSeq);
}
CCarModel * CBenzBuilder::GetCarModel()
{
    return m_pBenz;
}

BMWBuilder.h

#pragma once
#include "icarbuilder.h"
#include "CarModel.h"
#include <iostream>
#include <vector>
using std::string;
using std::vector;
class CBMWBuilder :
    public ICarBuilder
{
public:
    CBMWBuilder(void);
    ~CBMWBuilder(void);
    void SetSequence(vector<string> *pSeq);
    CCarModel * GetCarModel();
private:
    CCarModel *m_pBMW;
};

BMWBuilder.cpp

#include <stdio.h>
#include "BMWBuilder.h"
#include "BMWModel.h"
CBMWBuilder::CBMWBuilder(void)
{
    m_pBMW = new CBMWModel();
}
CBMWBuilder::~CBMWBuilder(void)
{
    delete m_pBMW;
}
void CBMWBuilder::SetSequence( vector<string> *pSeq )
{
    m_pBMW->SetSequence(pSeq);
}
CCarModel * CBMWBuilder::GetCarModel()
{
    return m_pBMW;
}

Director.h

#pragma once
#include "BenzModel.h"
#include "BMWModel.h"
#include "BenzBuilder.h"
#include "BMWBuilder.h"
#include <vector>
using std::vector;
class CDirector
{
public:
    CDirector(void);
    ~CDirector(void);
    CBenzModel * GetABenzModel();
    CBenzModel * GetBBenzModel();
    CBMWModel * GetCBMWModel();
    CBMWModel * GetDBMWModel();
private:
    vector<string> * m_pSeqence;
    CBenzBuilder * m_pBenzBuilder;
    CBMWBuilder * m_pBMWBuilder;
};

Director.cpp

#include <stdio.h>
#include "Director.h"
CDirector::CDirector(void)
{
    m_pBenzBuilder = new CBenzBuilder();
    m_pBMWBuilder = new CBMWBuilder();
    m_pSeqence = new vector<string>();
}
CDirector::~CDirector(void)
{
    delete m_pBenzBuilder;
    delete m_pBMWBuilder;
    delete m_pSeqence;
}
CBenzModel * CDirector::GetABenzModel()
{
    m_pSeqence->clear();
    m_pSeqence->push_back("start");
    m_pSeqence->push_back("stop");
    m_pBenzBuilder->SetSequence(m_pSeqence);
    return dynamic_cast<CBenzModel*>(m_pBenzBuilder->GetCarModel());
}
CBenzModel * CDirector::GetBBenzModel()
{
    m_pSeqence->clear();
    m_pSeqence->push_back("engine boom");
    m_pSeqence->push_back("start");
    m_pSeqence->push_back("stop");
    m_pBenzBuilder->SetSequence(m_pSeqence);
    return dynamic_cast<CBenzModel*>(m_pBenzBuilder->GetCarModel());
}
CBMWModel * CDirector::GetCBMWModel()
{
    m_pSeqence->clear();
    m_pSeqence->push_back("alarm");
    m_pSeqence->push_back("start");
    m_pSeqence->push_back("stop");
    m_pBMWBuilder->SetSequence(m_pSeqence);
    return static_cast<CBMWModel*>(m_pBMWBuilder->GetCarModel());
}
CBMWModel * CDirector::GetDBMWModel()
{
    m_pSeqence->clear();
    m_pSeqence->push_back("start");
    m_pBenzBuilder->SetSequence(m_pSeqence);
    return dynamic_cast<CBMWModel*>(m_pBMWBuilder->GetCarModel());
}
----------用同一个顺序,生成模型----------
奔驰引擎声音是这样....
奔驰发动...
奔驰停车...
奔驰引擎声音是这样....
奔驰发动...
奔驰停车...
----------批量生成模型----------
奔驰发动...
奔驰停车...
奔驰发动...
奔驰停车...
奔驰引擎声音是这样....
奔驰发动...
奔驰停车...
奔驰引擎声音是这样....
奔驰发动...
奔驰停车...
宝马鸣笛
宝马发动...
宝马停车...
宝马鸣笛
宝马发动...
宝马停车... 

代理模式

Provide a surrogate or placeholder for another object to control access to it.

为其他对象提供一种代理以控制对这个对象的访问。

代理模式

代理模式也叫做委托模式,它是一项基本设计技巧。许多其他的模式,如状态模式、策略模式、访问者模式本质上是在更特殊的场合采用了委托模式,而且在日常的应用中,代理模式可以提供非常好的访问控制。

● Subject抽象主题角色
抽象主题类可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求。

● RealSubject具体主题角色
也叫做被委托角色、被代理角色,是业务逻辑的具体执行者。

● Proxy代理主题角色
也叫做委托类、代理类。它负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实主题角色实现,并且在真实主题角色处理完毕前后做预处理和善后处理工作。

代理模式的优点:
● 职责清晰
真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件事务,附带的结果就是编程简洁清晰。

● 高扩展性
具体主题角色是随时都会发生变化的,只要它实现了接口,甭管它如何变化,都逃不脱如来佛的手掌(接口),那我们的代理类完全就可以在不做任何修改的情况下使用。

● 智能化
这在我们以上的讲解中还没有体现出来,不过在我们以下的动态代理章节中你就会看到代理的智能化有兴趣的读者也可以看看Struts是如何把表单元素映射到对象上的。

我相信第一次接触到代理模式的读者肯定很郁闷,为什么要用代理呀?想想现实世界吧,打官司为什么要找个律师?因为你不想参与中间过程的是是非非,只要完成自己的答辩就成,其他的比如事前调查、事后追查都由律师来搞定,这就是为了减轻你的负担。

个人理解:
代理模式应该是给传入的对象统一附加其他功能(函数)。


//主题类
class Subject
{
public:
  virtual Subject()=0;
  virtual ~Subject()=0;
  virtual void Request()=0;//具体代理的任务
};

//真实主题类
class ConcreteSubject:public Subject
{
public:
  ConcreteSubject();
  ~ConcreteSubject();
  void Request();
};

//代理类
class Proxy:public Subject
{
public:
  Proxy();
  Proxy(Subject* _sub);
  ~Proxy();

  void Request()//实现对委托者的委托任务执行与补偿
  {
    bef();
    this->_sub->Request();
    end();
  }

  void bef()
  {}

  void end()
  {}

private:
  Subject* _sub;
};

原型模式

Specify the kinds of objects to create using a prototypical instance,and create new objects by copying this prototype.

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

中介者模式

Define an object that encapsulates how a set of objects interact.Mediator promotes loose coupling by keeping objects from referring to each other explicitly,and it lets you vary their interaction independently.

用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

中介者模式
从类图中看,中介者模式由以下几部分组成:
● Mediator 抽象中介者角色
抽象中介者角色定义统一的接口,用于各同事角色之间的通信。
● Concrete Mediator 具体中介者角色
具体中介者角色通过协调各同事角色实现协作行为,因此它必须依赖于各个同事角色。
● Colleague 同事角色
每一个同事角色都知道中介者角色,而且与其他的同事角色通信的时候,一定要通过中介者角色协作。每个同事类的行为分为两种:一种是同事本身的行为,比如改变对象本身的状态,处理自己的行为等,这种行为叫做自发行为(Self-Method),与其他的同事类或中介者没有任何的依赖;第二种是必须依赖中介者才能完成的行为,叫做依赖方法(Dep-Method)。

中介者模式的优点
中介者模式的优点就是减少类间的依赖,把原有的一对多的依赖变成了一对一的依赖,同事类只依赖中介者,减少了依赖,当然同时也降低了类间的耦合。

中介者模式的缺点
中介者模式的缺点就是中介者会膨胀得很大,而且逻辑复杂,原本N个对象直接的相互依赖关系转换为中介者和同事类的依赖关系,同事类越多,中介者的逻辑就越复杂。

MVC框架
大家都应该使用过Struts,MVC框架,其中的C(Controller)就是一个中介者,叫做前端控制器(Front Controller),它的作用就是把M(Model,业务逻辑)和V(View,视图)隔离开,协调M和V协同工作,把M运行的结果和V代表的视图融合成一个前端可以展示的页面,减少M和V的依赖关系。MVC框架已经成为一个非常流行、成熟的开发框架,这也是中介者模式的优点的一个体现。


main.cpp

#include <iostream>
#include <string>
using namespace std;

class Colleague;

class Mediator {
public:
    virtual void Send(string message, Colleague* colleague) = 0;
    virtual ~Mediator() {}
};

class Colleague {
protected:
    Mediator* mediator;
public:
    Colleague(Mediator* m) { mediator = m; }
};

class ConcreteColleague1 : public Colleague {
public:
    ConcreteColleague1(Mediator* m) : Colleague(m) {}
    void Send(string message) {
        mediator->Send(message, this);
    }
    void Notify(string message) {
        cout << "ConcreteColleague1 received: " << message << endl;
    }
};

class ConcreteColleague2 : public Colleague {
public:
    ConcreteColleague2(Mediator* m) : Colleague(m) {}
    void Send(string message) {
        mediator->Send(message, this);
    }
    void Notify(string message) {
        cout << "ConcreteColleague2 received: " << message << endl;
    }
};

class ConcreteMediator : public Mediator {
private:
    ConcreteColleague1* c1;
    ConcreteColleague2* c2;
public:
    void set(ConcreteColleague1* c) { c1 = c; }
    void set(ConcreteColleague2* c) { c2 = c; }
    //通过colleague传入对象进行判断,然后选择行为。
    void Send(string message, Colleague* colleague) {
        if (colleague == c1) c2->Notify(message);
        else c1->Notify(message);
    }
};

int main() {
    ConcreteMediator* m = new ConcreteMediator();
    //让同事认识中介
    ConcreteColleague1* c1 = new ConcreteColleague1(m);
    ConcreteColleague2* c2 = new ConcreteColleague2(m);
    //让中介认识同事
    m->set(c1);
    m->set(c2);

    c1->Send("Hello");   // ConcreteColleague2 received: Hello
    c2->Send("World");  // ConcreteColleague1 received: World

    delete m;
    delete c1;
    delete c2;
    return 0;
}
g++ main.cpp
./a.out
ConcreteColleague2 received: Hello
ConcreteColleague1 received: World

为什么同事类要使用构造函数注入中介者,而中介者使用getter/setter方式注入同事类呢?这是因为同事类必须有中介者,而中介者却可以只有部分同事类。

命令模式

Encapsulate a request as an object,thereby letting you parameterize clients with different requests,queue or log requests,and support undoable operations.

将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。


main(),客户

CInvoker,命令接收者,如项目经理

IGroup,执行者接口

CRequirementGroup,实际执行者之一

CPageGroup,实际执行者之二

CCodePage,实际执行者之三

ICommand,命令接口

CAddRequirementCommand,Execute函数,将调用CRequirementGroup的多个命令。来组合执行用户发出的命令。

CDeletePageCommand,同上

… … 其它命令。

说明:客户只需要知道向Invoker发出命令(多个命令),而不是将命令直接传达给具体的执行者。当然,客户是需要知道都有什么命令的。

注意:客户只发命令,不需要知道由谁来执行和怎么执行,体现出高内聚的特点。用户在发出命令后,是允许撤回的,所以可以增加一个命令“Undo ”,Undo是状态的变更。

旅行社项目开发过程类图

Invoker.h

#pragma once
#include "ICommand.h"
class CInvoker
{
public:
    CInvoker(void);
    ~CInvoker(void);
    void SetCommand(ICommand *pcommand);
    void Action();
private:
    ICommand *m_pCommand;
};

Invoker.cpp

#include <stdio.h>
#include "Invoker.h"
CInvoker::CInvoker(void)
{
}
CInvoker::~CInvoker(void)
{
}
void CInvoker::SetCommand( ICommand *pcommand )
{
    this->m_pCommand = pcommand;
}
void CInvoker::Action()
{
    this->m_pCommand->Execute();
}

IGroup.h

#pragma once
class IGroup
{
public:
    IGroup(void)
    {
    }
    virtual ~IGroup(void)
    {
    }
    virtual void Find() = 0;
    virtual void Add() = 0;
    virtual void Delete() = 0;
    virtual void Change() = 0;
    virtual void Plan() = 0;
};

RequirementGroup.h

#pragma once
#include "igroup.h"
class CRequirementGroup :
    public IGroup
{
public:
    CRequirementGroup(void);
    ~CRequirementGroup(void);
    void Find();
    void Add();
    void Delete();
    void Change();
    void Plan();
};

RequirementGroup.cpp

#include <stdio.h>
#include "RequirementGroup.h"
#include <iostream>
using std::cout;
using std::endl;
CRequirementGroup::CRequirementGroup(void)
{
}
CRequirementGroup::~CRequirementGroup(void)
{
}
void CRequirementGroup::Find()
{
    cout << "找到需求组..." << endl;
}
void CRequirementGroup::Add()
{
    cout << "客户要求增加一项需求..." << endl;
}
void CRequirementGroup::Delete()
{
    cout << "要求删除一项需求..." << endl;
}
void CRequirementGroup::Change()
{
    cout << "客户要求修改一项需求..." << endl;
}
void CRequirementGroup::Plan()
{
    cout << "客户要求需求变更计划..." << endl;
}

PageGroup.h

#pragma once
#include "igroup.h"
class CPageGroup :
    public IGroup
{
public:
    CPageGroup(void);
    ~CPageGroup(void);
    void Find();
    void Add();
    void Delete();
    void Change();
    void Plan();
};

PageGroup.cpp

#include <stdio.h>
#include "PageGroup.h"
#include <iostream>
using std::cout;
using std::endl;
CPageGroup::CPageGroup(void)
{
}
CPageGroup::~CPageGroup(void)
{
}
void CPageGroup::Find()
{
    cout << "找到美工组..." << endl;
}
void CPageGroup::Add()
{
    cout << "客户要求增加一个页面..." << endl;
}
void CPageGroup::Delete()
{
    cout << "客户要求删除一个页面..." << endl;
}
void CPageGroup::Change()
{
    cout << "客户要求修改一个页面..." << endl;
}
void CPageGroup::Plan()
{
    cout << "客户要求页面变更计划..." << endl;
}

CodeGroup.h

#pragma once
#include "igroup.h"
class CCodeGroup :
    public IGroup
{
public:
    CCodeGroup(void);
    ~CCodeGroup(void);
    void Find();
    void Add();
    void Delete();
    void Change();
    void Plan();
};

CodeGroup.cpp

#include <stdio.h>
#include "CodeGroup.h"
#include <iostream>
using std::cout;
using std::endl;
CCodeGroup::CCodeGroup(void)
{
}
CCodeGroup::~CCodeGroup(void)
{
}
void CCodeGroup::Find()
{
    cout << "找到代码组..." << endl;
}
void CCodeGroup::Add()
{
    cout << "客户要求增加一项功能..." << endl;
}
void CCodeGroup::Delete()
{
    cout << "客户要求删除一项功能..." << endl;
}
void CCodeGroup::Change()
{
    cout << "客户要求修改一项功能..." << endl;
}
void CCodeGroup::Plan()
{
    cout << "客户要求代码变更计划..." << endl;
}

ICommand.h

#pragma once
#include "RequirementGroup.h"
#include "PageGroup.h"
#include "CodeGroup.h"
class ICommand
{
public:
    ICommand(void)
    {
        m_prg = new CRequirementGroup();
        m_ppg = new CPageGroup();
        m_pcg = new CCodeGroup();
    }
    virtual ~ICommand(void)
    {
        delete m_prg;
        delete m_ppg;
        delete m_pcg;
    }
    virtual void Execute() = 0;
protected:
    CRequirementGroup *m_prg;
    CPageGroup *m_ppg;
    CCodeGroup *m_pcg;
};

AddRequirementCommand.h

#pragma once
#include "icommand.h"
class CAddRequirementCommand :
    public ICommand
{
public:
    CAddRequirementCommand(void);
    ~CAddRequirementCommand(void);
    void Execute();
};

AddRequirementCommand.cpp

#include <stdio.h>
#include "AddRequirementCommand.h"
CAddRequirementCommand::CAddRequirementCommand(void)
{
}
CAddRequirementCommand::~CAddRequirementCommand(void)
{
}
void CAddRequirementCommand::Execute()
{
    //执行增另一项需求的命令
    this->ICommand::m_prg->Find();

    //增加一份需求
    this->ICommand::m_prg->Add();

    //给出计划
    this->ICommand::m_prg->Plan();
}

DeletePageCommand.h

#pragma once
#include "icommand.h"
class CDeletePageCommand :
    public ICommand
{
public:
    CDeletePageCommand(void);
    ~CDeletePageCommand(void);
    void Execute();
};

DeletePageCommand.cpp

#include <stdio.h>
#include "DeletePageCommand.h"
CDeletePageCommand::CDeletePageCommand(void)
{
}
CDeletePageCommand::~CDeletePageCommand(void)
{
}
void CDeletePageCommand::Execute()
{
    //执行增另一项需求的命令
    this->ICommand::m_ppg->Find();

    //增加一份需求
    this->ICommand::m_ppg->Delete();

    //给出计划
    this->ICommand::m_ppg->Plan();
}

Command.cpp

#include <stdio.h>
#include "IGroup.h"
#include "CodeGroup.h"
#include "PageGroup.h"
#include "RequirementGroup.h"
#include "Invoker.h"
#include "AddRequirementCommand.h"
#include "DeletePageCommand.h"
#include <iostream>
using std::cout;
using std::endl;

void DoIt()
{
    cout << "----------客户想增加一个需求----------" << endl;
    IGroup *rg = new CRequirementGroup();
    rg->Find();
    rg->Add();
    rg->Plan();
    delete rg;
    cout << endl;

    cout << "----------客户又想修改一个页面----------" << endl;
    IGroup *pg = new CPageGroup();
    pg->Find();
    pg->Add();
    pg->Plan();
    delete pg;
    cout << endl;

    cout << "----------客户又想删除一个功能----------" << endl;
    IGroup *cg = new CCodeGroup();
    cg->Find();
    cg->Add();
    cg->Plan();
    delete cg;
    cout << endl;
}

void DoNew()
{
    cout << "----------客户觉得烦了,希望只找一个人,并告诉他要做什么----------" << endl;
    cout << "----------客户要求增加一项需求----------" << endl;
    CInvoker gary;
    ICommand *pcommand = new CAddRequirementCommand();
    gary.SetCommand(pcommand);
    gary.Action();
    delete pcommand;
    cout << endl;

    //客户想要改动只需要找CInvoker就可以了。
    cout << "----------客户要求删除一个页面----------" << endl;
    CInvoker ricky;
    ICommand *pcommand2 = new CDeletePageCommand();
    ricky.SetCommand(pcommand2);
    ricky.Action();
    delete pcommand2;
    cout << endl;
}

int main()
{
    //客户原来的运行流程
    DoIt();

    //客户觉得麻烦了,每次改动都要找不同的组,谈不同的事
    //客户只想找一个人,告诉他要做什么就可以,不想关心由哪几个组来做和怎么做
    DoNew();

    _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
    _CrtDumpMemoryLeaks();
    return 0;
}
----------客户想增加一个需求----------
找到需求组...
客户要求增加一项需求...
客户要求需求变更计划...
----------客户又想修改一个页面---------
找到美工组...
客户要求增加一个页面...
客户要求页面变更计划...
----------客户又想删除一个功能----------
找到代码组...
客户要求增加一项功能...
客户要求代码变更计划...
----------客户觉得烦了,希望只找一个人,并告诉他要做什么----------
----------客户要求增加一项需求----------
找到需求组...
客户要求增加一项需求...
客户要求需求变更计划...
----------客户要求删除一个页面----------
找到美工组...
客户要求删除一个页面...
客户要求页面变更计划...  

责任链模式

Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request.Chain the receiving objects and pass the request along the chain until an object handles it.

使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。


main(),客户

IWomen,发出请求者接口

CWomen,请求者实现类

CHandler,处理请求抽象类

CFather,处理请求实现类,责任链之一

CHusband,处理请求实现类,责任链之二

CSon,处理请求实现类,责任链之三

说明:CHandler抽象类负责聚合责任链之中的其它处理对象,用SetNext来建立这个责任链。HandleMessage在处理请求时,会判断是否是自己要处理的请求,如果是则直接处理。如果不是,则查找下一个责任链上的处理对象,找到了则由下一个处理。

妇女“三从”类图

IWomen.h

#pragma once
#include <iostream>
using std::string;
class IWomen
{
public:
    IWomen(void)
    {
    }
    virtual ~IWomen(void)
    {
    }
    virtual int GetType() = 0;
    virtual string GetRequest() = 0;
};

//Women.h

#pragma once
#include "iwomen.h"
#include <iostream>
using std::string;
class CWomen :
    public IWomen
{
public:
    CWomen(int _type, string _request);
    ~CWomen(void);
    int GetType();
    string GetRequest();
private:
    int m_type;
    string m_request;
};

//Women.cpp

#include <stdio.h>
#include "Women.h"
CWomen::CWomen( int _type, string _request )
{
    this->m_type = _type;
    switch (this->m_type)
    {
    case 1:
        this->m_request.append("女儿的请求是:");
        this->m_request.append(_request);
        break;
    case 2:
        this->m_request.append("妻子的请求是:");
        this->m_request.append(_request);
        break;
    case 3:
        this->m_request.append("母亲的请求是:");
        this->m_request.append(_request);
        break;
    }
}
CWomen::~CWomen(void)
{
}
int CWomen::GetType()
{
    return m_type;
}
string CWomen::GetRequest()
{
    return m_request;
}

Handler.h

#pragma once
#include "IWomen.h"
class CHandler
{
public:
    CHandler(int _level);
    virtual ~CHandler(void);
    void HandleMessage(IWomen *pwomen);
    void SetNext(CHandler *phandler);
    virtual void Response(IWomen *pwomen) = 0;
private:
    int m_level;
    CHandler *m_pNextHandler;
};

Handler.cpp

#include <stdio.h>
#include "Handler.h"
#include <iostream>
using std::cout;
using std::endl;
CHandler::CHandler(int _level ) : m_level(_level)
{
    m_pNextHandler = NULL;
}
CHandler::~CHandler(void)
{
}
void CHandler::HandleMessage( IWomen *pwomen )
{
    if (pwomen->GetType() == this->m_level)
    {
        this->Response(pwomen);
    }
    else
    {
        if(this->m_pNextHandler != NULL)
            this->m_pNextHandler->HandleMessage(pwomen);
        else
            cout << "----------没地方请示了,不做处理!----------" << endl;
    }
}
void CHandler::SetNext( CHandler *phandler )
{
    m_pNextHandler = phandler;
}

Father.h

#pragma once
#include "handler.h"
#include "IWomen.h"
class CFather :
    public CHandler
{
public:
    CFather(void);
    ~CFather(void);
    void Response(IWomen *pwomen);
};

Father.cpp

#include <stdio.h>
#include "Father.h"
#include <iostream>
using std::cout;
using std::endl;
CFather::CFather(void) : CHandler(1)
{
}
CFather::~CFather(void)
{
}
void CFather::Response( IWomen *pwomen )
{
    cout << "女儿向父亲请示:" << endl;
    cout << pwomen->GetRequest().c_str() << endl;
    cout << "父亲的答复是:同意" << endl;
}

Husband.h

#pragma once
#include "handler.h"
#include "IWomen.h"
class CHusband :
    public CHandler
{
public:
    CHusband(void);
    ~CHusband(void);
    void Response(IWomen *pwomen);
};

Husband.cpp

#include <stdio.h>
#include "Husband.h"
#include <iostream>
using std::cout;
using std::endl;
CHusband::CHusband(void) : CHandler(2)
{
}
CHusband::~CHusband(void)
{
}
void CHusband::Response( IWomen *pwomen )
{
    cout << "妻子向丈夫请示:" << endl;
    cout << pwomen->GetRequest().c_str() << endl;
    cout << "丈夫的答复是:同意" << endl;
}

Son.h

#pragma once
#include "handler.h"
#include "IWomen.h"
class CSon :
    public CHandler
{
public:
    CSon(void);
    ~CSon(void);
    void Response(IWomen *pwomen);
};

Son.cpp

#include <stdio.h>
#include "Son.h"
#include <iostream>
using std::cout;
using std::endl;
CSon::CSon(void) : CHandler(3)
{
}
CSon::~CSon(void)
{
}
void CSon::Response( IWomen *pwomen )
{
    cout << "母亲向儿子请示:" << endl;
    cout << pwomen->GetRequest().c_str() << endl;
    cout << "儿子的答复是:同意" << endl;
}

// ChainofResponsibility.cpp

#include <stdio.h>
#include "IWomen.h"
#include "Women.h"
#include "Handler.h"
#include "Father.h"
#include "Husband.h"
#include "Son.h"
#include <iostream>
using std::cout;
using std::endl;
void DoIt()
{
   //cout << "----------原来的处理方式----------" << endl;
   INormalWomen* pwomen = new CNormalWomen(1, "我要出去逛街");
   INormalHandler* pfather = new CNormalFather();
   INormalHandler* phusband = new CNormalHusband();
   INormalHandler* pson = new CNormalSon();
   If (pwomen->GetType() == 1)
   //{
   //   cout << "女儿向父亲请示:" << endl;
   //   pfather->HandleMessage(pwomen);
   //}
   //else if (pwomen->GetType() == 2)
   //{
   //   cout << "妻子向丈夫请示:" << endl;
   //   phusband->HandleMessage(pwomen);
   //}
   //else if (pwomen->GetType() == 3)
   //{
   //   cout << "母亲向儿子请示:" << endl;
   //   pson->HandleMessage(pwomen);
   //}
   //else
   //{
   //   //什么也不做
   //}
   //delete pwomen;
   //delete pfather;
   //delete phusband;
   //delete pson;
}
void DoNew()
{
   cout << "----------使用模式后的处理方式----------" << endl;
   Handler.h, Handler.cpp, IWomen.h, Women.h, Women.cpp, Father.h, Father,cpp, Husband.h, Husband.cpp, Son.h, Son.cpp
   IWomen* pwomen1 = new CWomen(1, "我要出去逛街");
   IWomen* pwomen2 = new CWomen(2, "我要出去吃饭");
   IWomen* pwomen3 = new CWomen(3, "我也要出去吃饭");
   IWomen* pwomen4 = new CWomen(4, "我也要出去逛街");

   CHandler* pfather = new CFather();
   CHandler* phusband = new CHusband();
   CHandler* pson = new CSon();

   pfather->SetNext(phusband);
   phusband->SetNext(pson);

   pfather->HandleMessage(pwomen1);
   pfather->HandleMessage(pwomen2);
   pfather->HandleMessage(pwomen3);
   pfather->HandleMessage(pwomen4);

   delete pfather;
   delete phusband;
   delete pson;
   delete pwomen1;
   delete pwomen2;
   delete pwomen3;
   delete pwomen4;
}
int main()
{
   //反面
   DoIt();
   //要实现逻辑判断,即女性的请求先发送到父亲类,父亲类一看是自己要处理的,就回应进行处理。如果女儿已经出嫁了,那就把这个请求转发到女婿类来处理。依此类推,形成了一个责任链。
   DoNew();
   return 0;
}
----------使用模式后的处理方式----------
女儿向父亲请示:
女儿的请求是:我要出去逛街
父亲的答复是:同意
妻子向丈夫请示:
妻子的请求是:我要出去吃饭
丈夫的答复是:同意
母亲向儿子请示:
母亲的请求是:我也要出去吃饭
儿子的答复是:同意
----------没地方请示了,不做处理!----------    

装饰模式

Attach additional responsibilities to an object dynamically keeping the same interface.Decorators provide a flexible alternative to subclassing for extending functionality.

动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。


main(),老爸

ISchoolReport,成绩单接口

CFourthGradeSchoolReport,四年级成绩单

ReportDecorator,成绩单装饰器基类

HighScoreDecorator,最高分装饰器

SortDecorator,班级排名装饰器

说明:对“四年级成绩单”进行装饰,ReportDecorator必然有一个private变量指向ISchoolReport。

成绩单类图

// Decorator.cpp
//主程序

#include <stdio.h>
#include "ISchoolReport.h"
#include "FouthGradeSchoolReport.h"
#include "FouthGradeSchoolReport.h"
#include "HighScoreDecorator.h"
#include "SortDecorator.h"
#include <iostream>
using std::cout;
using std::endl;
void DoIt()
{
   ISchoolReport* psr = new CFouthGradeSchoolReport();
   psr->Report();//看成绩单
   psr->Sign("老三");//很开心,就签字了
   delete psr;
}
void DoNew()
{
   cout << "----------分部分进行装饰----------" << endl;
   ISchoolReport* psr = new CFouthGradeSchoolReport();//原装成绩单
   //
   ISchoolReport* pssr = new CSortDecorator(psr);//又加了成绩排名的说明
   ISchoolReport* phsr = new CHighScoreDecorator(pssr);//加了最高分说明的成绩单
   phsr->Report();//看成绩单
   phsr->Sign("老三");//很开心,就签字了

   //先装饰哪个不重要,顺序已经在装饰内部确定好,但一定要调用最后一个装饰器的接口。
   ISchoolReport *phsr = new CHighScoreDecorator(psr);//加了最高分说明的成绩单
   ISchoolReport *pssr = new CSortDecorator(phsr);//又加了成绩排名的说明
   //pssr->Report();//看成绩单
   //pssr->Sign("老三");//很开心,就签字了

   delete pssr;
   delete phsr;
   delete psr;
}
int main()
{
   //在装饰之前,可以用继承的办法,来进行简单的修饰
   DoIt();

   //但如果需要修饰的项目太多呢?或者装饰的项目不是固定的,继承显然会变得更复杂
   DoNew();

   _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
   _CrtDumpMemoryLeaks();
   return 0;
}

ISchoolReport.h

#pragma once
#include <iostream>
using std::string;
class ISchoolReport
{
public:
    ISchoolReport(void)
    {
    }
    virtual ~ISchoolReport(void)
    {
    }
    virtual void Report() = 0;
    virtual void Sign(string name) = 0;
};

FouthGradeSchoolReport.h

#pragma once
#include "ischoolreport.h"
class CFouthGradeSchoolReport :
    public ISchoolReport
{
public:
    CFouthGradeSchoolReport(void);
    ~CFouthGradeSchoolReport(void);
    void Report();
    void Sign(string name);
};

FouthGradeSchoolReport.cpp

#include <stdio.h>
#include "FouthGradeSchoolReport.h"
#include <iostream>
using std::cout;
using std::endl;
using std::string;
CFouthGradeSchoolReport::CFouthGradeSchoolReport(void)
{
}
CFouthGradeSchoolReport::~CFouthGradeSchoolReport(void)
{
}
void CFouthGradeSchoolReport::Report()
{
    cout << "尊敬的XXX家长:" << endl;
    cout << "......" << endl;
    cout << "语文62  数学65  体育98  自然63" << endl;
    cout << "......" << endl;
    cout << "                家长签名:" << endl;
}
void CFouthGradeSchoolReport::Sign(string name)
{
    cout << "家长签名为:" << name.c_str() << endl;
}

ReportDecorator.h

#pragma once
#include "ischoolreport.h"
class CReportDecorator :
    public ISchoolReport
{
public:
    CReportDecorator(ISchoolReport *psr);
    virtual ~CReportDecorator(void);
    void Report();
    void Sign(string name);
private:
    ISchoolReport *m_pSchoolReport;
};

ReportDecorator.cpp

#include <stdio.h>
#include "ReportDecorator.h"
#include <iostream>
using std::string;
CReportDecorator::CReportDecorator(ISchoolReport *psr)
{
    this->m_pSchoolReport = psr;
}
CReportDecorator::~CReportDecorator(void)
{
}
void CReportDecorator::Report()
{
    this->m_pSchoolReport->Report();
}
void CReportDecorator::Sign( string name )
{
    this->m_pSchoolReport->Sign(name);
}

HighScoreDecorator.h

#pragma once
#include "reportdecorator.h"
#include "ISchoolReport.h"
class CHighScoreDecorator :
    public CReportDecorator
{
public:
    CHighScoreDecorator(ISchoolReport *psr);
    ~CHighScoreDecorator(void);
    void Report();
private:
    void ReportHighScore();
};

HighScoreDecorator.cpp

#include <stdio.h>
#include "HighScoreDecorator.h"
#include <iostream>
using std::cout;
using std::endl;
CHighScoreDecorator::CHighScoreDecorator( ISchoolReport *psr ) : CReportDecorator(psr)
{
}
CHighScoreDecorator::~CHighScoreDecorator(void)
{
}
void CHighScoreDecorator::Report()
{
    this->ReportHighScore();
    this->CReportDecorator::Report();
}
void CHighScoreDecorator::ReportHighScore()
{
    cout << "这次考试语文最高是75, 数学是78, 自然是80" << endl;
}

SortDecorator.h

#pragma once
#include "reportdecorator.h"
#include "ISchoolReport.h"
class CSortDecorator :
    public CReportDecorator
{
public:
    CSortDecorator(ISchoolReport *psr);
    ~CSortDecorator(void);
    void Report();
private:
    void ReportSort();
};

SortDecorator.cpp

#include <stdio.h>
#include "SortDecorator.h"
#include <iostream>
using std::cout;
using std::endl;
CSortDecorator::CSortDecorator( ISchoolReport *psr ) : CReportDecorator(psr)
{
}
CSortDecorator::~CSortDecorator(void)
{
}
void CSortDecorator::ReportSort()
{
    cout << "我是排名第38名..." << endl;
}
void CSortDecorator::Report()
{
    this->CReportDecorator::Report();
    this->ReportSort();
}
尊敬的XXX家长:
......
语文62  数学65  体育98  自然63
......
家长签名:
家长签名为:老三
----------分部分进行装饰----------
这次考试语文最高是75, 数学是78, 自然是80
尊敬的XXX家长:
......
语文62  数学65  体育98  自然63
......
家长签名:
我是排名第38名...
家长签名为:老三   

策略模式

Define a family of algorithms,encapsulate each one,and make them interchangeable.

定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。

这个定义是非常明确、清晰的,“定义一组算法”,看看我们的三个计谋是不是三个算法?“将每个算法都封装起来”,封装类Context不就是这个作用吗?“使它们可以互换”当然可以互换了,都实现是相同的接口,那当然可以相互转化了。


main(),赵云

CContext,锦囊

IStrategy,策略接口

CBackDoor,策略之一

CGivenGreenLight,策略之二

CBlockEnemy,策略之三

说明:一个策略放到一个锦囊里。当用的时候,找到这个锦囊,从锦囊里拿出策略来使用。

注意:锦囊只是简单的装载和调用策略,锦囊里没有逻辑。策略会有更大的自主权,运行更多的逻辑。
注意:没有#include "IStrategy.h"可以自建一个IStrategy.h,包含#include "stdio.h即可。

策略模式

IStrategy.h

#pragma once

class IStrategy
{
public:
    IStrategy(void){};
    virtual ~IStrategy(void){};
    virtual void Operate(void) = 0;
};

Context.h

#pragma once
#include "IStrategy.h"
class CContext
{
public:
    CContext(IStrategy *pStrategy);
    ~CContext(void);
    void Operate(void);
private:
    IStrategy *m_pStrategy;
};

Context.cpp

#include <stdio.h>
#include "Context.h"
CContext::CContext(IStrategy *pStrategy)
{
    this->m_pStrategy = pStrategy;
}
CContext::~CContext(void)
{
    delete this->m_pStrategy;
}
void CContext::Operate(void)
{
    this->m_pStrategy->Operate();
}

BackDoor.h

#pragma once
#include "istrategy.h"
class CBackDoor :
    public IStrategy
{
public:
    CBackDoor(void);
    ~CBackDoor(void);
    void Operate(void);
};

BackDoor.cpp

#include <stdio.h>
#include "BackDoor.h"
#include <iostream>
using std::cout;
using std::endl;
CBackDoor::CBackDoor(void)
{
}
CBackDoor::~CBackDoor(void)
{
}
void CBackDoor::Operate(void)
{
    cout << "找乔国老帮忙,让吴国太给孙权施加压力" << endl;
}

GivenGreenLight.h

#pragma once
#include "istrategy.h"
class CGivenGreenLight :
    public IStrategy
{
public:
    CGivenGreenLight(void);
    ~CGivenGreenLight(void);
    void Operate(void);
};

GivenGreenList.cpp

#include <stdio.h>
#include "GivenGreenLight.h"
#include <iostream>
using std::cout;
using std::endl;
CGivenGreenLight::CGivenGreenLight(void)
{
}
CGivenGreenLight::~CGivenGreenLight(void)
{
}
void CGivenGreenLight::Operate(void)
{
    cout << "求吴国太开个绿灯,放行!" << endl;
}

BlockEnemy.h

#pragma once
#include "istrategy.h"
class CBlockEnemy :
    public IStrategy
{
public:
    CBlockEnemy(void);
    ~CBlockEnemy(void);
    void Operate(void);
};

BlockEnemy.cpp

#include <stdio.h>
#include "BlockEnemy.h"
#include <iostream>
using std::cout;
using std::endl;
CBlockEnemy::CBlockEnemy(void)
{
}
CBlockEnemy::~CBlockEnemy(void)
{
}
void CBlockEnemy::Operate()
{
    cout << "孙夫人断后,挡住追兵" << endl;
}

Strategy.cpp

#include <stdio.h>
#include "Context.h"
#include "BackDoor.h"
#include "GivenGreenLight.h"
#include "BlockEnemy.h"
#include <iostream>
using std::cout;
using std::endl;
int main()
{
    CContext *pContext;

    cout << "\14\n\n\n\n\17" << endl;
    cout << "----------刚刚到吴国的时候拆第一个----------" << endl;
    pContext = new CContext(new CBackDoor());
    pContext->Operate();
    delete pContext;

    cout << "\14\n\n\n\n\17" << endl;
    cout << "----------刘备乐不思蜀了,拆第二个了----------" << endl;
    pContext = new CContext(new CGivenGreenLight());
    pContext->Operate();
    delete pContext;

    cout << "\14\n\n\n\n\17" << endl;
    cout << "----------孙权的小兵追了,咋办?拆第三个----------" << endl;
    pContext = new CContext(new CBlockEnemy());
    pContext->Operate();
    delete pContext;

    _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
    _CrtDumpMemoryLeaks();
    return 0;
}
                
----------刚刚到吴国的时候拆第一个---------- 
找乔国老帮忙,让吴国太给孙权施加压力 
       
----------刘备乐不思蜀了,拆第二个了----------
求吴国太开个绿灯,放行! 
                  
----------孙权的小兵追了,咋办?拆第三个---------- 
孙夫人断后,挡住追兵

适配器模式

Convert the interface of a class into another interface clients expect.Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.

将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

适配器相当于转换接头,如投影仪的接口是DB9,电脑的接口是HDMI,因此使用DB9转HDMI转换器就可以使投影仪和电脑一起工作了!
适配器起到了解析作用,将一种形式的数据结构解析为另一种形式的数据结构。


main(),主程序

IUserInfo,本系统内接口

CUserInfo,本系统内实现类

IOuterUser,外系统接口

COuterUser,外系统实现类

COuterUserInfo,本系统内适配类

说明:COuterUserInfo实现IUserInfo接口,将外部系统实现类COuterUser转换成本系统内的接口IUserInfo。使用外部数据跟使用本系统内部数据一样。

注意:COuterUserInfo继承了IUserInfo,如果同时继承了COuterUser则是类适配器。如果COuterUserInfo只是使用了COuterUser则是对象适配器。

外调人员中转处理

IUserInfo.h
//系统内部的实体接口

#pragma once
#include <iostream>
using std::string;
class IUserInfo
{
public:
   IUserInfo(void)
   {
   }
   virtual ~IUserInfo(void)
   {
   }
   virtual string GetUserName() = 0;
   virtual string GetHomeAddress() = 0;
   virtual string GetMobileNumber() = 0;
   virtual string GetOfficeTelNumber() = 0;
   virtual string GetJobPosition() = 0;
   virtual string GetHomeTelNumber() = 0;
};

UserInfo.h
//系统内部实体类

#pragma once
#include "iuserinfo.h"
#include <iostream>
using std::string;
class CUserInfo :
   public IUserInfo
{
public:
   CUserInfo(void);
   ~CUserInfo(void);
   string GetUserName();
   string GetHomeAddress();
   string GetMobileNumber();
   string GetOfficeTelNumber();
   string GetJobPosition();
   string GetHomeTelNumber();
};

UserInfo.cpp

#include <stdio.h>
#include "UserInfo.h"
#include <iostream>
using std::cout;
using std::endl;
using std::string;
CUserInfo::CUserInfo(void)
{
}
CUserInfo::~CUserInfo(void)
{
}
string CUserInfo::GetUserName()
{
   cout << "姓名叫做..." << endl;
   return "0";
}
string CUserInfo::GetHomeAddress()
{
   cout << "这里是员工的家庭地址..." << endl;
   return "0";
}
string CUserInfo::GetMobileNumber()
{
   cout << "这个人的手机号码是0000..." << endl;
   return "0";
}
string CUserInfo::GetOfficeTelNumber()
{
   cout << "办公室电话是..." << endl;
   return "0";
}
string CUserInfo::GetJobPosition()
{
   cout << "这个人的职位是BOSS..." << endl;
   return "0";
}
string CUserInfo::GetHomeTelNumber()
{
   cout << "员工的家庭电话是..." << endl;
   return "0";
}

IOuterUser.h
//外部系统实体接口

#pragma once
#include "OuterUserBaseInfo.h"
#include "OuterUserHomeInfo.h"
#include "OuterUserOfficeInfo.h"
class IOuterUser
{
public:
   IOuterUser(void)
   {
   }
   ~IOuterUser(void)
   {
   }
   COuterUserBaseInfo* GetUserBaseInfo() {};
   COuterUserHomeInfo* GetUserHomeInfo() {};
   COuterUserOfficeInfo* GetUserOfficeInfo() {};
};

COuterUser.h
//外部系统实体类

#pragma once
#include "OuterUserBaseInfo.h"
#include "OuterUserHomeInfo.h"
#include "OuterUserOfficeInfo.h"
class COuterUser
{
public:
   COuterUser(void);
   ~COuterUser(void);
   COuterUserBaseInfo* GetUserBaseInfo();
   COuterUserHomeInfo* GetUserHomeInfo();
   COuterUserOfficeInfo* GetUserOfficeInfo();
};

COuterUser.cpp

#include <stdio.h>
#include "COuterUser.h"
#include "OuterUserBaseInfo.h"
#include "OuterUserHomeInfo.h"
#include "OuterUserOfficeInfo.h"
COuterUser::COuterUser(void)
{
}
COuterUser::~COuterUser(void)
{
}
COuterUserBaseInfo* COuterUser::GetUserBaseInfo()
{
   return new COuterUserBaseInfo();
}
COuterUserHomeInfo* COuterUser::GetUserHomeInfo()
{
   return new COuterUserHomeInfo();
}
COuterUserOfficeInfo* COuterUser::GetUserOfficeInfo()
{
   return new COuterUserOfficeInfo();
}

OuterUserBaseInfo.h

#pragma once
#include <iostream>
using std::cout;
using std::endl;
using std::string;
class COuterUserBaseInfo
{
public:
   COuterUserBaseInfo(void)
   {
   }
   ~COuterUserBaseInfo(void)
   {
   }
   string GetUserName()
   {
      cout << "姓名叫做..." << endl;
      return "0";
   }
   string GetMobileNumber()
   {
      cout << "这个人的手机号码是0001..." << endl;
      return "0";
   }
};

OuterUserHomeInfo.h

#pragma once
#include <iostream>
using std::cout;
using std::endl;
using std::string;
class COuterUserHomeInfo
{
public:
   COuterUserHomeInfo(void)
   {
   }
   ~COuterUserHomeInfo(void)
   {
   }
   string GetHomeAddress()
   {
      cout << "这里是员工的家庭地址..." << endl;
      return "0";
   }
   string GetHomeTelNumber()
   {
      cout << "员工的家庭电话是..." << endl;
      return "0";
   }
};

OuterUserOfficeInfo.h

#pragma once
#include <iostream>
using std::cout;
using std::endl;
using std::string;
class COuterUserOfficeInfo
{
public:
   COuterUserOfficeInfo(void)
   {
   }
   ~COuterUserOfficeInfo(void)
   {
   }
   string GetOfficeTelNumber()
   {
      cout << "办公室电话是..." << endl;
      return "0";
   }
   string GetJobPosition()
   {
      cout << "这个人的职位是BOSS..." << endl;
      return "0";
   }
};

OuterUserInfo.h
//由IUserInfo接口派生的实体类,并引入外部系统实体的实例

#pragma once
#include "iuserinfo.h"
#include "COuterUser.h"
#include <iostream>
using std::string;
class COuterUserInfo :
    public IUserInfo
{
public:
    COuterUserInfo(void);
    ~COuterUserInfo(void);
    string GetUserName();
    string GetHomeAddress();
    string GetMobileNumber();
    string GetOfficeTelNumber();
    string GetJobPosition();
    string GetHomeTelNumber();
private:
    COuterUser *m_pOuterUser;
};

OuterUserInfo.cpp

#include <stdio.h>
#include "OuterUserInfo.h"
#include "OuterUserBaseInfo.h"
#include "OuterUserHomeInfo.h"
#include "OuterUserOfficeInfo.h"
#include <iostream>
using std::cout;
using std::endl;
using std::string;
COuterUserInfo::COuterUserInfo(void)
{
   m_pOuterUser = new COuterUser();
}
COuterUserInfo::~COuterUserInfo(void)
{
   delete m_pOuterUser;
}
string COuterUserInfo::GetUserName()
{
   COuterUserBaseInfo* pBaseInfo = m_pOuterUser->GetUserBaseInfo();
   pBaseInfo->GetUserName();
   delete pBaseInfo;
   pBaseInfo = NULL;
   return "0";
}
string COuterUserInfo::GetHomeAddress()
{
   COuterUserHomeInfo* pHomeInfo = m_pOuterUser->GetUserHomeInfo();
   pHomeInfo->GetHomeAddress();
   delete pHomeInfo;
   pHomeInfo = NULL;
   return "0";
}
string COuterUserInfo::GetMobileNumber()
{
   COuterUserBaseInfo* pBaseInfo = m_pOuterUser->GetUserBaseInfo();
   pBaseInfo->GetMobileNumber();
   delete pBaseInfo;
   pBaseInfo = NULL;
   return "0";
}
string COuterUserInfo::GetOfficeTelNumber()
{
   COuterUserOfficeInfo* pOfficeInfo = m_pOuterUser->GetUserOfficeInfo();
   pOfficeInfo->GetOfficeTelNumber();
   delete pOfficeInfo;
   pOfficeInfo = NULL;
   return "0";
}
string COuterUserInfo::GetJobPosition()
{
   COuterUserOfficeInfo* pOfficeInfo = m_pOuterUser->GetUserOfficeInfo();
   pOfficeInfo->GetJobPosition();
   delete pOfficeInfo;
   pOfficeInfo = NULL;
   return "0";
}
string COuterUserInfo::GetHomeTelNumber()
{
   COuterUserHomeInfo* pHomeInfo = m_pOuterUser->GetUserHomeInfo();
   pHomeInfo->GetHomeTelNumber();
   delete pHomeInfo;
   pHomeInfo = NULL;
   return "0";
}

Adapter.cpp
//使用方法

#include <stdio.h>
#include "IOuterUser.h"
#include "IUserInfo.h"
#include "UserInfo.h"
#include "OuterUserInfo.h"
void DoIt()
{
   IUserInfo* pYourGirl = new CUserInfo();
   for (int i = 0; i < 101; i += 20)
   {
      pYourGirl->GetMobileNumber();
   }
   delete pYourGirl;
}
void NowDoIt()
{
   IUserInfo* pYourGirl = new COuterUserInfo();

   for (int i = 0; i < 101; i += 20)
   {
      pYourGirl->GetMobileNumber();
   }

   delete pYourGirl;
}


int main()
{
   DoIt();

   NowDoIt();

   return 0;
}
这个人的手机号码是0000...
这个人的手机号码是0000...
这个人的手机号码是0000...
这个人的手机号码是0000...
这个人的手机号码是0000...
这个人的手机号码是0000...
这个人的手机号码是0001...
这个人的手机号码是0001...
这个人的手机号码是0001...
这个人的手机号码是0001...
这个人的手机号码是0001...
这个人的手机号码是0001... 

迭代器模式

Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

它提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节。


main(),客户

IProject,产品接口

CProject,产品类

IIterator,迭代器接口

IProjectIterator,产品迭代器接口

CProjectIterator,产品迭代器实现类

说明:CProject实现产品类,能够返回一个迭代器的指针。这个迭代器将封装产品类里的一个数组。所以迭代器在运行Next函数时,可以遍历这个数组的所有元素。

简单来说,就是用代码实现vector::iterator或vector::const_iterator。
注意:
如果你是做Java开发,尽量不要自己写迭代器模式!省省吧,使用Java提供的Iterator一般就能满足你的要求了!

项目信息类图

IProject.h

#pragma once
#include "IProjectIterator.h"
#include <iostream>
using std::string;
class IProject
{
public:
    IProject(void)
    {
    }
    virtual ~IProject(void)
    {
    }
    virtual void Add(string name, int num, int cost) = 0;
    virtual string GetProjectInfo() = 0;
    virtual IProjectIterator* GetIterator() = 0;
    virtual void Erase() = 0;
};

Project.h

#pragma once
#include "iproject.h"
#include "IProjectIterator.h"
#include <iostream>
#include <vector>
using std::string;
using std::vector;
class CProject :
    public IProject
{
public:
    CProject(void);
    CProject(string name, int num, int cost);
    ~CProject(void);
    string GetProjectInfo();
    void Add(string name, int num, int cost);
    IProjectIterator * GetIterator();
    void Erase();
private:
    string m_name;
    int m_num;
    int m_cost;
    vector<IProject*> m_projectList;
};

Project.cpp

#include <stdio.h>
#include "Project.h"
#include "ProjectIterator.h"
#include <iostream>
#include <vector>
#include<sstream>
using std::string;
using std::vector;
using std::ostringstream;
using std::to_string;
CProject::CProject(void)
{
   m_name = "";
   m_num = 0;
   m_cost = 0;
}
CProject::CProject(string name, int num, int cost) :m_name(name), m_num(num), m_cost(cost)
{
}
CProject::~CProject(void)
{
}
string CProject::GetProjectInfo()
{
   string info = "";
   info.append("项目名称是:");
   info.append(this->m_name);
   info.append("\t项目人数:");
   info.append(to_string(m_num));
   info.append("\t项目费用:");
   info.append(to_string(m_cost));
   return info;
}
void CProject::Add(string name, int num, int cost)
{
   this->m_projectList.push_back(new CProject(name, num, cost));
}
IProjectIterator* CProject::GetIterator()
{
   return new CProjectIterator(this->m_projectList);
}
void CProject::Erase()
{
   vector<IProject*>::reverse_iterator projectDelIt = m_projectList.rbegin();
   for (; projectDelIt != m_projectList.rend(); projectDelIt++)
   {
      delete (*projectDelIt);
      (*projectDelIt) = NULL;
   }
   m_projectList.clear();
}

IIterator.h

#pragma once
class IProject;
class IIterator
{
public:
    IIterator(void)
    {
    }
    virtual ~IIterator(void)
    {
    }
    virtual bool HasNext() = 0;
    virtual IProject * Next() = 0;
};

IProjectIterator.h

#pragma once
#include "iiterator.h"
class IProject;
class IProjectIterator :
    public IIterator
{
public:
    IProjectIterator(void)
    {
    }
    virtual ~IProjectIterator(void)
    {
    }
    virtual bool HasNext() = 0;
    virtual IProject * Next() = 0;
};

ProjectIterator.h

#pragma once
#include "iprojectiterator.h"
#include "IProject.h"
#include <vector>
using std::vector;
class CProjectIterator :
    public IProjectIterator
{
public:
    CProjectIterator(vector<IProject *> pl);
    ~CProjectIterator(void);
    bool HasNext();
    IProject * Next();
private:
    vector<IProject *> m_projectList;
    size_t m_currentItem;
};

ProjectIterator.cpp

#include <stdio.h>
#include "ProjectIterator.h"
CProjectIterator::CProjectIterator(vector<IProject*> pl) : m_projectList(pl)
{
   m_currentItem = 0;
}
CProjectIterator::~CProjectIterator(void)
{
}
bool CProjectIterator::HasNext()
{
   bool b = true;
   if (m_currentItem >= m_projectList.size())
      b = false;
   return b;
}
IProject* CProjectIterator::Next()
{
   IProject* pp = m_projectList.at(m_currentItem++);
   return pp;
}

Iterator.cpp

#include <stdio.h>
#include "IProject.h"
#include "Project.h"
#include "ProjectIterator.h"
#include <iostream>
#include <vector>
#include<string>
using std::vector;
using std::cout;
using std::endl;
using std::to_string;
void DoIt()
{
   cout << "----------未使用迭代模式----------" << endl;
   vector<IProject*> projectList;

   projectList.push_back(new CProject("星球大战项目", 10, 100000));
   projectList.push_back(new CProject("扭转时空项目", 100, 10000000));
   projectList.push_back(new CProject("超人改造项目", 10000, 1000000000));

   for (int i = 4; i < 6; i++)
   {
      string name = "";
      name.append("第");
      name.append(to_string(i));
      name.append("个项目");
      projectList.push_back(new CProject(name, i * 5, i * 1000000));
   }

   vector<IProject*>::const_iterator projectIt = projectList.begin();
   for (; projectIt != projectList.end(); projectIt++)
      cout << (*projectIt)->GetProjectInfo().c_str() << endl;

   vector<IProject*>::reverse_iterator projectDelIt = projectList.rbegin();
   for (; projectDelIt != projectList.rend(); projectDelIt++)
   {
      delete (*projectDelIt);
      (*projectDelIt) = NULL;
   }
   projectList.clear();
}
void DoNew()
{
   cout << "----------使用迭代模式----------" << endl;
   IProject* pproject = new CProject();
   pproject->Add("星球大战项目", 10, 100000);
   pproject->Add("扭转时空项目", 100, 10000000);
   pproject->Add("超人改造项目", 10000, 1000000000);

   for (int i = 4; i < 6; i++)
   {
      string name = "";
      name.append("第");
      name.append(to_string(i));
      name.append("个项目");
      pproject->Add(name, i * 5, i * 1000000);
   }

   IProjectIterator* pprojectIt = pproject->GetIterator();
   while (pprojectIt->HasNext())
   {
      IProject* p = dynamic_cast<IProject*>(pprojectIt->Next());
      cout << p->GetProjectInfo().c_str() << endl;
   }
   delete pprojectIt;
   pprojectIt = NULL;
   pproject->Erase();
   delete pproject;
   pproject = NULL;
}
int main()
{
   //使用Iterator模式之前
   DoIt();

   //使用Iterator
   DoNew();

   _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
   _CrtDumpMemoryLeaks();

   return 0;
}
----------未使用迭代模式----------
项目名称是:星球大战项目        项目人数:10    项目费用:100000
项目名称是:扭转时空项目        项目人数:100   项目费用:10000000
项目名称是:超人改造项目        项目人数:10000 项目费用:1000000000
项目名称是:第4个项目   项目人数:20    项目费用:4000000
项目名称是:第5个项目   项目人数:25    项目费用:5000000
----------使用迭代模式----------
项目名称是:星球大战项目        项目人数:10    项目费用:100000
项目名称是:扭转时空项目        项目人数:100   项目费用:10000000
项目名称是:超人改造项目        项目人数:10000 项目费用:1000000000
项目名称是:第4个项目   项目人数:20    项目费用:4000000
项目名称是:第5个项目   项目人数:25    项目费用:5000000   

组合模式

Compose objects into tree structures to represent part-whole hierarchies.Composite lets clients treat individual objects and compositions of objects uniformly.

将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。


main(),客户

CCorpNode,抽象基类,实现基本信息

CBranchNode,树枝节点,实现Addordinate()函数和GetSubordinate()函数

CLeafNode,叶子节点,IsLeaf属性总是“true”

说明:组合模式主要是实现在CBranchNode对象里增加对其它对象的数组,如vector<CCorpNode*>,数组里可以存放CBranchNode和CLeafNode对象。这样方便进行遍历操作。

注意:组合模式有透明组合模式和安全组合模式。透明组合模式是将Addordinate和GetSubordinate这两个函数也抽象到CCorpNode基类里,这增加了操作叶子节点的难度,更易出现逻辑问题。所以尽量使用安全模式。

这个简单了,可以想像一下TreeView和TreeNode基本上是这个意思了,将很多数据组织在一块。

组织架构

Branch.h

#pragma once
#include "ibranch.h"
#include "ICorp.h"
#include <vector>
#include <iostream>
using std::vector;
using std::string;
class CBranch :
    public IBranch, ICorp
{
public:
    CBranch(void);
    CBranch(string name, string pos, int salary);
    ~CBranch(void);
    void Add(ICorp *pcorp);
    vector<ICorp*> GetSubordinateInfo();
    string GetInfo();
private:
    string m_name;
    string m_position;
    int m_salary;
    vector<ICorp*> m_subordinateList;
};

BranchNode.h

#pragma once
#include "corpnode.h"
#include "CorpNode.h"
#include <vector>
#include <iostream>
using std::vector;
using std::string;
class CBranchNode :
    public CCorpNode
{
public:
    CBranchNode(void);
    CBranchNode(string name, string pos, int salary);
    ~CBranchNode(void);
    void Add(CCorpNode *pcorpNode);
    vector<CCorpNode*> GetSubordinateInfo();
    bool IsLeaf();
private:
    vector<CCorpNode*> m_subordinateList;
};

CorpNode.h

#pragma once
#include <iostream>
using std::string;
class CCorpNode
{
public:
    CCorpNode();
    CCorpNode(string _name, string _pos, int _salary);
    virtual ~CCorpNode(void);
    virtual string GetInfo();
    void SetParent(CCorpNode *_pParent);
    CCorpNode * GetParent();
    virtual bool IsLeaf() = 0;
private:
    string m_name;
    string m_position;
    int m_salary;
protected:
    bool m_isLeaf;
    CCorpNode *m_pParent;
};

IBranch.h

#pragma once
#include "ICorp.h"
#include <vector>
#include <iostream>
using std::vector;
using std::string;
class IBranch
{
public:

    IBranch(void)
    {
    }

    virtual ~IBranch(void)
    {
    }
    virtual void Add(ICorp *pcorp) = 0;
    virtual vector<ICorp*> GetSubordinateInfo() = 0;
};

ICorp.h

#pragma once
#include <iostream>
using std::string;
class ICorp
{
public:

    ICorp(void)
    {
    }

    virtual ~ICorp(void)
    {
    }
    virtual string GetInfo() = 0;
};

Leaf.h

#pragma once
#include "icorp.h"
#include <iostream>
using std::string;
class CLeaf :
    public ICorp
{
public:
    CLeaf(void);
    CLeaf(string name, string pos, int salary);
    ~CLeaf(void);
    string GetInfo();
private:
    string m_name;
    string m_position;
    int m_salary;
};

LeafNode.h

#pragma once
#include "corpnode.h"
class CLeafNode :
    public CCorpNode
{
public:
    CLeafNode(void);
    CLeafNode(string name, string pos, int salary);
    ~CLeafNode(void);
    bool IsLeaf();
};

Branch.cpp

#include <stdio.h>
#include "Branch.h"
#include "..\CommonDeclare\Convert.h"


CBranch::CBranch(void)
{
}

CBranch::CBranch( string name, string pos, int salary ) : m_name(name), m_position(pos), m_salary(salary)
{

}


CBranch::~CBranch(void)
{
}

void CBranch::Add( ICorp *pcorp )
{
    m_subordinateList.push_back(pcorp);
}

vector<ICorp*> CBranch::GetSubordinateInfo()
{
    return this->m_subordinateList;
}

string CBranch::GetInfo()
{
    string info = "";
    info.append("姓名:");
    info.append(this->m_name);
    info.append("\t职位:");
    info.append(this->m_position);
    info.append("\t薪水:");
    info.append(CConvert::ToString(this->m_salary));
    return info;
}

BranchNode.cpp

#include <stdio.h>
#include "BranchNode.h"


CBranchNode::CBranchNode(void)
{
    m_isLeaf = false;
}


CBranchNode::CBranchNode( string name, string pos, int salary ) : CCorpNode(name, pos, salary)
{
    m_isLeaf = false;
}


CBranchNode::~CBranchNode(void)
{
}

void CBranchNode::Add( CCorpNode *pcorpNode )
{
    pcorpNode->SetParent(this);
    m_subordinateList.push_back(pcorpNode);
}

vector<CCorpNode*> CBranchNode::GetSubordinateInfo()
{
    return this->m_subordinateList;
}

bool CBranchNode::IsLeaf()
{
    return m_isLeaf;
}

Composite.cpp

// Composite.cpp : 定义控制台应用程序的入口点。
//

#include <stdio.h>
#include "BranchNode.h"
#include "LeafNode.h"
#include <vector>
#include <iostream>
using std::vector;
using std::string;
using std::cout;
using std::endl;


void DoIt()
{
    //注未使用模式调用ICorp、CLeaf、CBranch这三个类来组织。
}

string GetTreeInfo(CBranchNode * proot)
{
    vector<CCorpNode*> subordinateList = proot->GetSubordinateInfo();
    string info = "";

    vector<CCorpNode*>::const_iterator it = subordinateList.begin();
    for (; it != subordinateList.end(); it++)
    {
        if ((*it)->IsLeaf())
        {
            info.append((*it)->GetInfo());
            info.append("\n");
        }
        else
        {
            info.append((*it)->GetInfo());
            info.append("\n");
            info.append(GetTreeInfo(dynamic_cast<CBranchNode*>(*it)));
        }
    }
    return info;
}


void DoNew()
{
    CBranchNode root("赵大", "总经理", 100000);

    CBranchNode devDep("钱大", "研发部门经理", 10000);
    CBranchNode saleDep("孙大", "销售部门经理", 20000);
    CBranchNode financeDep("李大", "财务部门经理", 30000);

    CBranchNode firstDevGroup("周三也斜", "开发一组组长", 5000);
    CBranchNode secondDevGroup("吴大棒槌", "开发二组组长", 6000);

    CLeafNode a("a", "开发人员", 2000);
    CLeafNode b("b", "开发人员", 2000);
    CLeafNode c("c", "开发人员", 2000);
    CLeafNode d("d", "开发人员", 2000);
    CLeafNode e("e", "开发人员", 2000);
    CLeafNode f("f", "开发人员", 2000);
    CLeafNode g("g", "开发人员", 2000);
    CLeafNode h("h", "开发人员", 5000);
    CLeafNode i("i", "开发人员", 4000);
    CLeafNode j("j", "开发人员", 5000);
    CLeafNode k("k", "CEO秘书", 8000);
    CLeafNode zheng("郑老六", "研发部副经理", 20000);

    root.Add(&k);CEO有三个部门经理和一个秘书
    root.Add(&devDep);
    root.Add(&saleDep);
    root.Add(&financeDep);

    devDep.Add(&zheng);//开发部有一个副经理和两个小组
    devDep.Add(&firstDevGroup);
    devDep.Add(&secondDevGroup);

    firstDevGroup.Add(&a);
    firstDevGroup.Add(&b);
    firstDevGroup.Add(&c);
    secondDevGroup.Add(&d);
    secondDevGroup.Add(&e);
    secondDevGroup.Add(&f);

    saleDep.Add(&g);
    saleDep.Add(&h);

    financeDep.Add(&i);
    financeDep.Add(&j);

    cout << root.GetInfo().c_str() << endl;
    cout << GetTreeInfo(&root).c_str() << endl;
}


int main()
{
    //未使用模式的调用。
    DoIt();

    //使用组合模式后的调用。
    DoNew();
    return 0;
}

CorpNode.cpp

#include <stdio.h>
#include "CorpNode.h"
#include "..\CommonDeclare\Convert.h"


CCorpNode::CCorpNode(void)
{
    m_name = "";
    m_position = "";
    m_salary = 0;
}


CCorpNode::CCorpNode(string _name, string _pos, int _salary) : m_name(_name), m_position(_pos), m_salary(_salary)
{
}


CCorpNode::~CCorpNode(void)
{
}

string CCorpNode::GetInfo()
{
    string info = "";
    info.append("姓名:");
    info.append(this->m_name);
    info.append("\t职位:");
    info.append(this->m_position);
    info.append("\t薪水:");
    info.append(CConvert::ToString(this->m_salary));
    return info;
}

void CCorpNode::SetParent( CCorpNode *_parent )
{
    this->m_pParent = _parent;
}

CCorpNode * CCorpNode::GetParent()
{
    return this->m_pParent;
}

Leaf.cpp

#include <stdio.h>
#include "Leaf.h"
#include "..\CommonDeclare\Convert.h"


CLeaf::CLeaf(void)
{
    m_name = "";
    m_position = "";
    m_salary = 0;
}


CLeaf::CLeaf( string name, string pos, int salary ) : m_name(name), m_position(pos), m_salary(salary)
{
}


CLeaf::~CLeaf(void)
{
}


string CLeaf::GetInfo()
{
    string info = "";
    info.append("姓名:");
    info.append(this->m_name);
    info.append("\t职位:");
    info.append(this->m_position);
    info.append("\t薪水:");
    info.append(CConvert::ToString(this->m_salary));
    return info;
}

LeafNode.cpp

#include <stdio.h>
#include "LeafNode.h"


CLeafNode::CLeafNode(void)
{
    m_isLeaf = true;
}


CLeafNode::CLeafNode( string name, string pos, int salary ) : CCorpNode(name, pos, salary)
{
    m_isLeaf = true;
}


CLeafNode::~CLeafNode(void)
{
}


bool CLeafNode::IsLeaf()
{
    return m_isLeaf;
}
姓名:赵大      职位:总经理    薪水:100000
姓名:k 职位:CEO秘书   薪水:8000
姓名:钱大      职位:研发部门经理      薪水:10000
姓名:郑老六    职位:研发部副经理      薪水:20000
姓名:周三也斜  职位:开发一组组长      薪水:5000
姓名:a 职位:开发人员  薪水:2000
姓名:b 职位:开发人员  薪水:2000
姓名:c 职位:开发人员  薪水:2000
姓名:吴大棒槌  职位:开发二组组长      薪水:6000
姓名:d 职位:开发人员  薪水:2000
姓名:e 职位:开发人员  薪水:2000
姓名:f 职位:开发人员  薪水:2000
姓名:孙大      职位:销售部门经理      薪水:20000
姓名:g 职位:开发人员  薪水:2000
姓名:h 职位:开发人员  薪水:5000
姓名:李大      职位:财务部门经理      薪水:30000
姓名:i 职位:开发人员  薪水:4000
姓名:j 职位:开发人员  薪水:5000  

观察者模式

Define a one-to-many dependency between objects so that when one object changes state,all its dependents are notified and updated automatically.

定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。

观察者模式

● Subject被观察者
定义被观察者必须实现的职责,它必须能够动态地增加、取消观察者。它一般是抽象类或者是实现类,仅仅完成作为被观察者必须实现的职责:管理观察者并通知观察者。
● Observer观察者
观察者接收到消息后,即进行update(更新方法)操作,对接收到的信息进行处理。
● ConcreteSubject具体的被观察者
定义被观察者自己的业务逻辑,同时定义对哪些事件进行通知。
● ConcreteObserver具体的观察者
每个观察在接收到消息后的处理反应是不同,各个观察者有自己的处理逻辑。

传统方式用多线程技术实现监听,而线程和死循环会极大的增加开销,为了避免这种开销,可以使用观察者模式。

这种模式有多种叫法,现整理如下,每一行都是相同的东西:
主题,被观察者,调用者
订阅者,观察者,被调用者
注册,订阅


主题用于管理订阅者,当发布者发生变化时,主题广播给所有订阅者,然后所有订阅者做统一动作.

主题
Subject.h

#ifndef __SUBJECT__H__
#define __SUBJECT__H__
#include "Observer.h"
#include <list>
#include <string>
using namespace std;
class Observer;
class Subject
{
public:
    Subject();
    virtual ~Subject();
    virtual void attach(Observer* obs);
    virtual void detach(Observer* obs);
    virtual void Notify();
    virtual void setState(const string& str) = 0;
    virtual string getState() = 0;

private:
    list<Observer*>* _observers;
};


class ConcreteSubject : public Subject {
public:
    ConcreteSubject();
    ~ConcreteSubject();
    void setState(const string& str);
    string getState();
private:
    string state;
};
#endif

Subject.cpp

#include "Subject.h"
#include <iostream>
#include <list>
using namespace std;

Subject::Subject() {
    _observers = new list<Observer*>;
}
Subject::~Subject() {

}

void Subject::attach(Observer* obs) {
    if (obs != NULL) {
        _observers->push_front(obs);
    }
}

void Subject::detach(Observer* obs) {
    if (obs != NULL) {
        _observers->remove(obs);
    }
}

void Subject::Notify() {

    list<Observer*>::iterator iter;//遍历更新
    for (iter = _observers->begin(); iter != _observers->end(); iter++) {
        (*iter)->update(this);
    }
}

ConcreteSubject::ConcreteSubject() {
    this->state = '\0';
}

ConcreteSubject::~ConcreteSubject() {

}

string ConcreteSubject::getState() {
    return this->state;
}

void ConcreteSubject::setState(const string& str) {
    this->state = str;
}

观察者

Observer.h

#ifndef __OBSERVER__H__
#define __OBSERVER__H__
#include "Subject.h"
#include <string>
using namespace std;
class Subject;
class Observer {
public:
    Observer();
    virtual ~Observer();
    virtual void update(Subject* subject) = 0;
    virtual void printInfo() = 0;
public:
    std::string state;

};

class ConcreteObserver:public Observer 
{
public:
    ConcreteObserver(Subject* sub);
    ~ConcreteObserver();
    void update(Subject* sub);
    void printInfo();
private:
    Subject* _sub;

};
#endif

Observer.cpp

#include "Observer.h"
#include <list>
#include <iostream>

using namespace std;

Observer::Observer() {
    state = '\0';
}

Observer::~Observer() {

}

ConcreteObserver::ConcreteObserver(Subject* sub) {
    _sub = sub;
    _sub->attach(this);
}


ConcreteObserver::~ConcreteObserver() {
    _sub->detach(this);
    if (_sub != 0) {
        delete _sub;
    }
}



void ConcreteObserver::update(Subject* subject) {
    state = subject->getState();
    this->printInfo();
}


void ConcreteObserver::printInfo() {
   // string str = _sub->getState();
    cout << "ConcreteObserver observer.... " << _sub->getState() << endl;
}

主函数
main.cpp

#include "Observer.h"
#include "Subject.h"
#include <iostream>
using namespace std;
int main() {
    //新建一个被监听对象sub(主题)
    Subject* sub = new ConcreteSubject();

    //新建一个监听者obA ,并初始化为监听sub
    ConcreteObserver* obA = new ConcreteObserver(sub);
    ConcreteObserver* obB = new ConcreteObserver(sub);

    //验证此时消息为空
    obA->printInfo();
    obB->printInfo();

    //被监听者开始改变
    sub->setState("大家好,我现在已经发布了最新消息");
    //被监听者发布广播
    sub->Notify();

    return 0;
}
g++ main.cpp Subject.cpp Observer.cpp 
./a.out
ConcreteObserver observer.... 
ConcreteObserver observer.... 
ConcreteObserver observer.... 大家好,我现在已经发布了最新消息
ConcreteObserver observer.... 大家好,我现在已经发布了最新消息

这是被监听者和监听者直接对接的模型,还有一种是增加了第三方通信平台,监听者向平台注册,被监听者将更新信息发送给消息平台,然后平台进行发放广播。我怀疑这是不是代理模式?

门面模式

Provide a unified interface to a set of interfaces in a subsystem.Facade defines a higher-level interface that makes the subsystem easier to use.

要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。

门面模式注重“统一的对象”,也就是提供一个访问子系统的接口,除了这个接口不允许有任何访问子系统的行为发生。
简单说,就是将复杂的逻辑封装起来,对外公开简单的接口,由客户程序调用。


main(),客户

ILetterProcess,接口

CLetterProcessImpl,信件处理的4个函数

CLetterPolice,警察

CModenPostOffice,邮局

说明:邮局对外只有一个窗口,接收信件内容和邮件地址。对内调用邮件处理的4个函数。将复杂逻辑封装在邮局的里面,当需要增加警察来检查信件时,只需在邮局内增加警察检查信件的方法。

写信过程类图

ILetterProcess.h

#pragma once
#include <iostream>
using std::string;
class ILetterProcess
{
public:
    ILetterProcess(void);
    virtual ~ILetterProcess(void);
    virtual void WriteContext(string context) = 0;
    virtual void FillEnvelope(string address) = 0;
    virtual void LetterIntoEnvelope() = 0;
    virtual void SendLetter() = 0;
};

ILetterProcess.cpp

#include <stdio.h>
#include "ILetterProcess.h"
ILetterProcess::ILetterProcess(void)
{
}
ILetterProcess::~ILetterProcess(void)
{
}

LetterprocessImpl.h

#pragma once
#include "iletterprocess.h"
class CLetterProcessImpl :
    public ILetterProcess
{
public:
    CLetterProcessImpl(void);
    ~CLetterProcessImpl(void);

    void WriteContext(string context);
    void FillEnvelope(string address);
    void LetterIntoEnvelope();
    void SendLetter();
};

LetterProcessImpl.cpp

#include <stdio.h>
#include "LetterProcessImpl.h"
#include <iostream>
using std::string;
using std::cout;
using std::endl;
CLetterProcessImpl::CLetterProcessImpl(void)
{
}
CLetterProcessImpl::~CLetterProcessImpl(void)
{
}
void CLetterProcessImpl::WriteContext(string context)
{
    cout << "填写信的内容... ..." << endl;
}
void CLetterProcessImpl::FillEnvelope(string address)
{
    cout << "填写收件人地址及姓名... ..." << endl;
}
void CLetterProcessImpl::LetterIntoEnvelope()
{
    cout << "把信放到信封中..." << endl;
}
void CLetterProcessImpl::SendLetter()
{
    cout << "邮递信件..." << endl;
}

ModenPostOffice.h

#pragma once
#include "ILetterProcess.h"
#include "LetterProcessImpl.h"
#include "LetterPolice.h"
#include <iostream>
using std::string;
class CModenPostOffice
{
public:
    CModenPostOffice(void);
    ~CModenPostOffice(void);
    void SendLetter(string context, string address);
private:
    ILetterProcess *m_pLetterProcess;
    CLetterPolice *m_pLetterPolice;
};

ModenPostOffice.cpp

#include <stdio.h>
#include "ModenPostOffice.h"
CModenPostOffice::CModenPostOffice(void)
{
    this->m_pLetterProcess = new CLetterProcessImpl();
    this->m_pLetterPolice = new CLetterPolice();
}
CModenPostOffice::~CModenPostOffice(void)
{
    delete m_pLetterProcess;
    delete m_pLetterPolice;
}
void CModenPostOffice::SendLetter( string context, string address )
{
    //帮忙写信
    m_pLetterProcess->WriteContext(context);
    //写好信封
    m_pLetterProcess->FillEnvelope(address);
    //警察要检查信件了
    m_pLetterPolice->CheckLetter(m_pLetterProcess);
    //把信放到信封中
    m_pLetterProcess->LetterIntoEnvelope();
    //邮递信件
    m_pLetterProcess->SendLetter();
}

LetterPolice.h

#pragma once
#include "ILetterProcess.h"
class CLetterPolice
{
public:
   CLetterPolice(void) {};
   ~CLetterPolice(void) {};
   void CheckLetter(ILetterProcess* pLetterProcess) {};
};

LetterPolice.cpp

#include <stdio.h>
#include "LetterPolice.h"
CLetterPolice::CLetterPolice(void)
{
}
CLetterPolice::~CLetterPolice(void)
{
}
void CLetterPolice::CheckLetter( ILetterProcess *pLetterProcess )
{

    //检查信件,此处省略一万字。
    return;
}

Facade.cpp

#include <stdio.h>
#include "ILetterProcess.h"
#include "LetterProcessImpl.h"
#include "ModenPostOffice.h"
#include<iostream>
using std::string;
using std::cout;
using std::endl;
void DoItByPostOffice()
{
    CModenPostOffice modenPostOffice;
    string context = "Hello, It's me, do you know who I am? I'm your old lover. I'd like to ... ...";
    string address = "Happy Road No. 666, Beijing City, China";
    modenPostOffice.SendLetter(context, address);
}
void DoItYourself()
{
    ILetterProcess *pLetterProcess = new CLetterProcessImpl();
    pLetterProcess->WriteContext("Hello, It's me, do you know who I am? I'm your old lover. I'd like to ... ...");
    pLetterProcess->FillEnvelope("Happy Road No. 666, Beijing City, China");
    pLetterProcess->LetterIntoEnvelope();
    pLetterProcess->SendLetter();
    delete pLetterProcess;
}
int main()
{
    //现在的调用方式。对于客户来说确实简单多了。
    //如需要增加逻辑,例如让警察来检查邮件。可以在邮局里完成这项工作。
    DoItByPostOffice();

    //原来的调用方式。
    DoItYourself();

    _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
    _CrtDumpMemoryLeaks();

    return 0;
}
填写信的内容... ...
填写收件人地址及姓名... ...
把信放到信封中...
邮递信件...
填写信的内容... ...
填写收件人地址及姓名... ...
把信放到信封中...
邮递信件...   

备忘录模式

Without violating encapsulation,capture and externalize an object’s internal state so that the object can be restored to this state later.

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

访问者模式

Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.

封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。

BaseVisitor.h

#pragma once
#include "ivisitor.h"
#include "CommonEmployee.h"
#include "Manager.h"
#include <iostream>
using std::string;
class CBaseVisitor :
    public IVisitor
{
public:
    CBaseVisitor(void);
    ~CBaseVisitor(void);
    void Visit(CCommonEmployee commonEmployee);
    void Visit(CManager manager);
    int GetTotalSalary();
private:
    string GetBasicInfo(CEmployee *pemployee);
    string GetManagerInfo(CManager manager);
    string GetCommonEmployee(CCommonEmployee employee);
    static const int MANAGER_COEFFICENT = 5;
    static const int COMMONEMPLOYEE_COEFFICENT = 2;
    int m_commonTotal;
    int m_managerTotal;
    void CalCommonSalary(int salary);
    void CalManagerSalary(int salary);
};

CommonEmployee.h

#pragma once
#include "employee.h"
#include "IVisitor.h"
#include <iostream>
using std::string;
class CCommonEmployee :
    public CEmployee
{
public:
    CCommonEmployee(void);
    ~CCommonEmployee(void);
    string GetJob();
    void SetJob(string job);
    void Accept(IVisitor *pVisitor);
protected:
    string GetOtherInfo();
private:
    string m_job;
};

Employee.h

#pragma once
#include "IVisitor.h"
#include <iostream>
using std::string;
class CEmployee
{
public:
    static int MALE;
    static int FEMALE;
    CEmployee(void);
    virtual ~CEmployee(void);
    string GetName();
    void SetName(string name);
    int GetSalary();
    void SetSalary(int v);
    int GetSex();
    void SetSex(int v);
    virtual void Accept(IVisitor *pVisitor) = 0;
private:
    string m_name;
    int m_salary;
    int m_sex;
};

IVisitor.h

#pragma once

class CCommonEmployee;
class CManager;
class IVisitor
{
public:

    IVisitor(void)
    {
    }

    virtual ~IVisitor(void)
    {
    }
    virtual void Visit(CCommonEmployee commonEmployee) = 0;
    virtual void Visit(CManager manager) = 0;
    virtual int GetTotalSalary() = 0;
};

Manager.h

#pragma once
#include "employee.h"
#include "IVisitor.h"
#include <iostream>
using std::string;
class CManager :
    public CEmployee
{
public:
    CManager(void);
    ~CManager(void);
    string GetPerformance();
    void SetPerformance(string per);
    void Accept(IVisitor *pVisitor);
protected:
    string GetOtherInfo();
private:
    string m_performance;
};

BaseVisitor.cpp

#include <stdio.h>
#include "..\CommonDeclare\Convert.h"
#include "BaseVisitor.h"
#include <iostream>
using std::string;
using std::cout;
using std::endl;


CBaseVisitor::CBaseVisitor(void)
{
    m_commonTotal = 0;
    m_managerTotal = 0;
}


CBaseVisitor::~CBaseVisitor(void)
{
}

void CBaseVisitor::Visit(CCommonEmployee commonEmployee)
{
    cout << this->GetCommonEmployee(commonEmployee).c_str() << endl;
    this->CalCommonSalary(commonEmployee.GetSalary());
}

void CBaseVisitor::Visit(CManager manager)
{
    cout << this->GetManagerInfo(manager).c_str() << endl;
    this->CalManagerSalary(manager.GetSalary());
}

string CBaseVisitor::GetBasicInfo(CEmployee *pemployee)
{
    string info = "";
    info.append("姓名:");
    info.append(pemployee->GetName());
    info.append("\t");
    info.append("性别:");
    info.append(CConvert::ToString(pemployee->GetSex()));
    info.append("\t");
    info.append("薪水:");
    info.append(CConvert::ToString(pemployee->GetSalary()));
    info.append("\t");
    return info;
}

string CBaseVisitor::GetManagerInfo(CManager manager)
{
    string basicInfo = this->GetBasicInfo(&manager);
    string otherInfo = "";
    otherInfo.append("业绩:");
    otherInfo.append(manager.GetPerformance());
    otherInfo.append("\t");
    basicInfo.append(otherInfo);
    return basicInfo;
}

string CBaseVisitor::GetCommonEmployee(CCommonEmployee employee)
{
    string basicInfo = this->GetBasicInfo(&employee);
    string otherInfo = "";
    otherInfo.append("工作:");
    otherInfo.append(employee.GetJob());
    otherInfo.append("\t");
    basicInfo.append(otherInfo);
    return basicInfo;
}

int CBaseVisitor::GetTotalSalary()
{
    return this->m_commonTotal + this->m_managerTotal;
}

void CBaseVisitor::CalCommonSalary(int salary)
{
    this->m_commonTotal += salary;
}

void CBaseVisitor::CalManagerSalary(int salary)
{
    this->m_managerTotal += salary;
}

CommonEmployee.cpp

#include <stdio.h>
#include "CommonEmployee.h"
#include <iostream>
using std::string;


CCommonEmployee::CCommonEmployee(void)
{
    this->m_job = "";
}


CCommonEmployee::~CCommonEmployee(void)
{
}

string CCommonEmployee::GetJob()
{
    return this->m_job;
}

void CCommonEmployee::SetJob(string job)
{
    this->m_job = job;
}

string CCommonEmployee::GetOtherInfo()
{
    string job = "";
    job.append("工作:");
    job.append(this->m_job);
    job.append("\t");
    return job;
}

void CCommonEmployee::Accept(IVisitor *pVisitor)
{
    pVisitor->Visit(*this);
}

Employee.cpp

#include <stdio.h>
#include "Employee.h"
int CEmployee::MALE = 0;
int CEmployee::FEMALE = 1;

CEmployee::CEmployee(void)
{
}


CEmployee::~CEmployee(void)
{
}

string CEmployee::GetName()
{
    return m_name;
}

void CEmployee::SetName( string name )
{
    m_name = name;
}

int CEmployee::GetSalary()
{
    return m_salary;
}

void CEmployee::SetSalary( int v )
{
    m_salary = v;
}

int CEmployee::GetSex()
{
    return m_sex;
}

void CEmployee::SetSex( int v )
{
    m_sex = v;
}

Manager.cpp

#include <stdio.h>
#include "Manager.h"
#include <iostream>
using std::string;


CManager::CManager(void)
{
    this->m_performance = "";
}


CManager::~CManager(void)
{
}

string CManager::GetPerformance()
{
    return m_performance;
}

void CManager::SetPerformance(string per)
{
    this->m_performance = per;
}

string CManager::GetOtherInfo()
{
    string info = "";
    info.append("业绩:");
    info.append(this->m_performance);
    info.append("\t");
    return info;
}

void CManager::Accept(IVisitor *pVisitor)
{
    pVisitor->Visit(*this);
}

Visitor.cpp

// Visitor.cpp : 定义控制台应用程序的入口点。
//

#include <stdio.h>
#include "Employee.h"
#include "CommonEmployee.h"
#include "Manager.h"
#include "BaseVisitor.h"
#include "..\CommonDeclare\Convert.h"
#include <vector>
#include <iostream>
using std::vector;
using std::cout;
using std::endl;


void MockEmployee(vector<CEmployee*> *pvce)
{
    CCommonEmployee *pZhangSan = new CCommonEmployee();
    pZhangSan->SetJob("编写Java程序,绝对的蓝领、苦工加搬运工");
    pZhangSan->SetName("张三");
    pZhangSan->SetSalary(1800);
    pZhangSan->SetSex(CEmployee::MALE);
    pvce->push_back(pZhangSan);

    CCommonEmployee *pLiSi = new CCommonEmployee();
    pLiSi->SetJob("页面美工,审美素质太不流行了!");
    pLiSi->SetName("李四");
    pLiSi->SetSalary(1900);
    pLiSi->SetSex(CEmployee::FEMALE);
    pvce->push_back(pLiSi);

    CManager *pWangWu = new CManager();
    pWangWu->SetPerformance("基本上是负值,但是我会拍马屁呀");
    pWangWu->SetName("王五");
    pWangWu->SetSalary(1900);
    pWangWu->SetSex(CEmployee::FEMALE);
    pvce->push_back(pWangWu);
}


void DoIt()
{
    vector<CEmployee*> vce;
    MockEmployee(&vce);
    vector<CEmployee*>::const_iterator readIt = vce.begin();

    CBaseVisitor visitor;
    for (; readIt != vce.end(); readIt ++)
    {
        (*readIt)->Accept(&visitor);
    }
    cout << "本公司的月工资总额是:" << CConvert::ToString(visitor.GetTotalSalary()).c_str() << endl;

    vector<CEmployee*>::reverse_iterator delIt = vce.rbegin();
    for (; delIt != vce.rend(); delIt++)
    {
        delete (*delIt);
        (*delIt) = NULL;
    }
    vce.clear();
}


int main()
{
    DoIt();
    return 0;
}
姓名:张三      性别:0 薪水:1800      工作:编写Java程序,绝对的蓝领、苦工加搬运工
姓名:李四      性别:1 薪水:1900      工作:页面美工,审美素质太不流行了!
姓名:王五      性别:1 薪水:1900      业绩:基本上是负值,但是我会拍马屁呀
本公司的月工资总额是:5600    

状态模式

Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.

当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。

main(),客户

CLiftState,电梯状态抽象类

CCloseingState,电梯门关闭

COpenningState,电梯门打开

CRunningState,电梯运行

CStoppingState,电梯停止

CContext,电梯的控制面板

说明:CContext保持电梯的状态,并提供操作的接口函数。当函数被调用时,CContext直接调用当前状态的相应函数。由状态的接口函数来确定是否可以执行这个动作,以及修改状态为执行这个动作后的状态。

看代码:第一块是不使用模式的做法,第二块是使用模式的做法,在main()函数里会有调用的方式。

电梯的类图

ILift.h

#pragma once
class ILift
{
public:

    ILift(void)
    {
    }

    virtual ~ILift(void)
    {
    }
    static const int OPENING_STATE = 1;
    static const int CLOSING_STATE = 2;
    static const int RUNNING_STATE = 3;
    static const int STOPPING_STATE = 4;
    virtual void SetState(int state) = 0;
    virtual void Open() = 0;
    virtual void Close() = 0;
    virtual void Run() = 0;
    virtual void Stop() = 0;
};

Lift.h

#pragma once
#include "ilift.h"
class CLift :
    public ILift
{
public:
    CLift(void);
    ~CLift(void);
    void SetState(int state);
    void Open();
    void Close();
    void Run();
    void Stop();
private:
    int m_state;
    void OpenWithoutLogic();
    void CloseWithoutLogic();
    void RunWithoutLogic();
    void StopWithoutLogic();
};

Lift.cpp

#include <stdio.h>
#include "Lift.h"
#include <iostream>
using std::cout;
using std::endl;

CLift::CLift(void)
{
    this->m_state = 0;
}

CLift::~CLift(void)
{
}

void CLift::SetState(int state)
{
    this->m_state = state;
}

void CLift::Open()
{
    switch(this->m_state)
    {
    case OPENING_STATE:
        break;
    case CLOSING_STATE:
        this->OpenWithoutLogic();
        this->SetState(OPENING_STATE);
        break;
    case RUNNING_STATE:
        break;
    case STOPPING_STATE:
        this->OpenWithoutLogic();
        this->SetState(OPENING_STATE);
        break;
    }
}

void CLift::Close()
{
    switch(this->m_state)
    {
    case OPENING_STATE:
        this->CloseWithoutLogic();
        this->SetState(CLOSING_STATE);
        break;
    case CLOSING_STATE:
        break;
    case RUNNING_STATE:
        break;
    case STOPPING_STATE:
        break;
    }
}

void CLift::Run()
{
    switch(this->m_state)
    {
    case OPENING_STATE:
        break;
    case CLOSING_STATE:
        this->RunWithoutLogic();
        this->SetState(RUNNING_STATE);
        break;
    case RUNNING_STATE:
        break;
    case STOPPING_STATE:
        this->RunWithoutLogic();
        this->SetState(RUNNING_STATE);
        break;
    }
}

void CLift::Stop()
{
    switch(this->m_state)
    {
    case OPENING_STATE:
        break;
    case CLOSING_STATE:
        this->StopWithoutLogic();
        this->SetState(CLOSING_STATE);
        break;
    case RUNNING_STATE:
        this->StopWithoutLogic();
        this->SetState(CLOSING_STATE);
        break;
    case STOPPING_STATE:
        break;
    }
}

void CLift::OpenWithoutLogic()
{
    cout << "电梯门开启..." << endl;
}

void CLift::CloseWithoutLogic()
{
    cout << "电梯门关闭..." << endl;
}

void CLift::RunWithoutLogic()
{
    cout << "电梯上下跑起来..." << endl;
}

void CLift::StopWithoutLogic()
{
    cout << "电梯停止了..." << endl;
}

LiftState.h

#pragma once
class CContext;
class CLiftState
{
public:
    CLiftState(void);
    virtual ~CLiftState(void);
    void SetContext(CContext *pContext);
    virtual void Open() = 0;
    virtual void Close() = 0;
    virtual void Run() = 0;
    virtual void Stop() = 0;
protected:
    CContext *m_pContext;
};

LiftState.cpp

#include <stdio.h>
#include "LiftState.h"

CLiftState::CLiftState(void)
{
}

CLiftState::~CLiftState(void)
{
}

void CLiftState::SetContext( CContext *pContext )
{
    m_pContext = pContext;
}

CloseingState.h

#pragma once
#include "liftstate.h"
class CCloseingState :
    public CLiftState
{
public:
    CCloseingState(void);
    ~CCloseingState(void);
    void Open();
    void Close();
    void Run();
    void Stop();
};

CloseingState.cpp

#include <stdio.h>
#include "CloseingState.h"
#include "Context.h"
#include <iostream>
using std::cout;
using std::endl;

CCloseingState::CCloseingState(void)
{
}

CCloseingState::~CCloseingState(void)
{
}

void CCloseingState::Open()
{
    this->CLiftState::m_pContext->SetLiftState(CContext::pOpenningState);
    this->CLiftState::m_pContext->GetLiftState()->Open();
}

void CCloseingState::Close()
{
    cout << "电梯门关闭..." << endl;
}

void CCloseingState::Run()
{
    this->CLiftState::m_pContext->SetLiftState(CContext::pRunningState);
    this->CLiftState::m_pContext->GetLiftState()->Run();
}

void CCloseingState::Stop()
{
    this->CLiftState::m_pContext->SetLiftState(CContext::pStoppingState);
    this->CLiftState::m_pContext->GetLiftState()->Stop();
}

OpenningState.h

#pragma once
#include "liftstate.h"
class COpenningState :
    public CLiftState
{
public:
    COpenningState(void);
    ~COpenningState(void);
    void Open();
    void Close();
    void Run();
    void Stop();
};

OpenningState.cpp

#include <stdio.h>
#include "OpenningState.h"
#include "Context.h"
#include <iostream>
using std::cout;
using std::endl;

COpenningState::COpenningState(void)
{
}

COpenningState::~COpenningState(void)
{
}

void COpenningState::Open()
{
    cout << "电梯门开启..." << endl;
}

void COpenningState::Close()
{
    this->CLiftState::m_pContext->SetLiftState(CContext::pCloseingState);
    this->CLiftState::m_pContext->GetLiftState()->Close();
}

void COpenningState::Run()
{
    //do nothing
}

void COpenningState::Stop()
{
    //do nothing
}

RunningState.h

#pragma once
#include "liftstate.h"
class CRunningState :
    public CLiftState
{
public:
    CRunningState(void);
    ~CRunningState(void);
    void Open();
    void Close();
    void Run();
    void Stop();
};

RunningState.cpp

#include <stdio.h>
#include "RunningState.h"
#include "Context.h"
#include <iostream>
using std::cout;
using std::endl;

CRunningState::CRunningState(void)
{
}

CRunningState::~CRunningState(void)
{
}

void CRunningState::Open()
{
    //do nothing
}

void CRunningState::Close()
{
    //do nothing
}

void CRunningState::Run()
{
    cout << "电梯上下跑..." << endl;
}

void CRunningState::Stop()
{
    this->CLiftState::m_pContext->SetLiftState(CContext::pStoppingState);
    this->CLiftState::m_pContext->GetLiftState()->Stop();
}

StoppingState.h

#pragma once
#include "liftstate.h"
class CStoppingState :
    public CLiftState
{
public:
    CStoppingState(void);
    ~CStoppingState(void);
    void Open();
    void Close();
    void Run();
    void Stop();
};

StoppingState.cpp

#include <stdio.h>
#include "StoppingState.h"
#include "Context.h"
#include <iostream>
using std::cout;
using std::endl;

CStoppingState::CStoppingState(void)
{
}

CStoppingState::~CStoppingState(void)
{
}

void CStoppingState::Open()
{
    this->CLiftState::m_pContext->SetLiftState(CContext::pOpenningState);
    this->CLiftState::m_pContext->GetLiftState()->Open();
}

void CStoppingState::Close()
{
    //do nothing
}

void CStoppingState::Run()
{
    this->CLiftState::m_pContext->SetLiftState(CContext::pRunningState);
    this->CLiftState::m_pContext->GetLiftState()->Run();
}

void CStoppingState::Stop()
{
    cout << "电梯停止了..." << endl;
}

Context.h

#pragma once
#include "LiftState.h"
#include "OpenningState.h"
#include "CloseingState.h"
#include "RunningState.h"
#include "StoppingState.h"
class CContext
{
public:
    CContext(void);
    ~CContext(void);
    static COpenningState *pOpenningState;
    static CCloseingState *pCloseingState;
    static CRunningState *pRunningState;
    static CStoppingState *pStoppingState;
    CLiftState * GetLiftState();
    void SetLiftState(CLiftState *pLiftState);
    void Open();
    void Close();
    void Run();
    void Stop();
private:
    CLiftState *m_pLiftState;
};

Context.cpp

#include <stdio.h>
#include "Context.h"
COpenningState* CContext::pOpenningState = NULL;
CCloseingState* CContext::pCloseingState = NULL;
CRunningState* CContext::pRunningState = NULL;
CStoppingState* CContext::pStoppingState = NULL;

CContext::CContext(void)
{
    m_pLiftState = NULL;
    pOpenningState = new COpenningState();
    pCloseingState = new CCloseingState();
    pRunningState = new CRunningState();
    pStoppingState = new CStoppingState();
}

CContext::~CContext(void)
{
    delete pOpenningState;
    pOpenningState = NULL;
    delete pCloseingState;
    pCloseingState = NULL;
    delete pRunningState;
    pRunningState = NULL;
    delete pStoppingState;
    pStoppingState = NULL;
}

CLiftState * CContext::GetLiftState()
{
    return m_pLiftState;
}

void CContext::SetLiftState(CLiftState *pLiftState)
{
    this->m_pLiftState = pLiftState;
    this->m_pLiftState->SetContext(this);
}

void CContext::Open()
{
    this->m_pLiftState->Open();
}

void CContext::Close()
{
    this->m_pLiftState->Close();
}

void CContext::Run()
{
    this->m_pLiftState->Run();
}

void CContext::Stop()
{
    this->m_pLiftState->Stop();
}

// State.cpp : 定义控制台应用程序的入口点。

#include <stdio.h>
#include "ILift.h"
#include "Lift.h"
#include "Context.h"
#include "OpenningState.h"
#include "CloseingState.h"
#include "RunningState.h"
#include "StoppingState.h"
#include <iostream>
using std::cout;
using std::endl;

void DoIt()
{
    ILift.h, Lift.h, Lift.cpp
    ILift *pLift = new CLift();
    pLift->SetState(ILift::STOPPING_STATE);//电梯的初始条件是停止状态。
    pLift->Open();//首先是电梯门开启,人进去
    pLift->Close();//然后电梯门关闭
    pLift->Run();//再然后,电梯跑起来,向上或者向下
    pLift->Stop();//最后到达目的地,电梯停下来
    delete pLift;
}


void DoNew()
{
    LiftState.h, LiftState.cpp, OpenningState.h, CloseingState.h, RunningState.h, StoppingState.h
    Context.h, Context.cpp
    CContext context;
    CCloseingState closeingState;
    context.SetLiftState(&closeingState);
    context.Close();
    context.Open();
    context.Run();
    context.Stop();
}

int main()
{
    cout << "----------使用模式之前----------" << endl;
    DoIt();
    cout << "----------使用模式之后----------" << endl;
    DoNew();

    _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
    _CrtDumpMemoryLeaks();
    return 0;
}
----------使用模式之前----------
电梯门开启...
电梯门关闭...
电梯上下跑起来...
电梯停止了...
----------使用模式之后----------
电梯门关闭...
电梯门开启...     

解释器模式

Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.

给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。

享元模式

Use sharing to support large numbers of fine-grained objects efficiently.

使用共享对象可有效地支持大量的细粒度的对象。

桥梁模式

Decouple an abstraction from its implementation so that the two can vary independently.

将抽象和实现解耦,使得两者可以独立地变化。


main(),客户

IProduct,产品接口

CHouse,房子

CIPod,ipod

CClothes,服装

CNewCorp,桥梁类,MakeMoney()是桥梁方法

CNewHouseCorp,只能生产房子,所以构造函数是CHouse*

CShanZhaiCorp,什么赚钱就生产什么,所以构造函数是IProduct*

说明:客户直接使用CNewHouseCorp和CShanZhaiCorp类,在main()函数里构造产品,然后传到这两个类里。这两个类的MakeMoney()函数,先调用基类的MakeMoney(),然后分别执行各自的逻辑。

注意:CNewCorp起到了桥梁的作用。可以分别增加产品和公司。

使用快速变化的类图

NewCorp.h

#pragma once
#include "IProduct.h"
class CNewCorp
{
public:
    CNewCorp(IProduct *pproduct);
    virtual ~CNewCorp(void);
    void MakeMoney();
private:
    IProduct *m_pProduct;
};

NewCorp.cpp

#include <stdio.h>
#include "NewCorp.h"
CNewCorp::CNewCorp( IProduct *pproduct )
{
    this->m_pProduct = pproduct;
}
CNewCorp::~CNewCorp(void)
{
}
void CNewCorp::MakeMoney()
{
    //每个公司都是一样,先生产
    this->m_pProduct->BeProducted();

    //然后销售
    this->m_pProduct->BeSelled();
}

NewHouseCorp.h

#pragma once
#include "newcorp.h"
#include "House.h"
class CNewHouseCorp :
    public CNewCorp
{
public:
    CNewHouseCorp(CHouse *pHouse);
    ~CNewHouseCorp(void);
    void MakeMoney();
};

NewHouseCorp.cpp

#include <stdio.h>
#include "NewHouseCorp.h"
#include <iostream>
using std::cout;
using std::endl;
CNewHouseCorp::CNewHouseCorp(CHouse *pHouse) : CNewCorp(pHouse)
{
}
CNewHouseCorp::~CNewHouseCorp(void)
{
}
void CNewHouseCorp::MakeMoney()
{
    this->CNewCorp::MakeMoney();
    cout << "房地产公司赚大钱了..." << endl;
}

ShanZhaiCorp.h

#pragma once
#include "newcorp.h"
#include "IProduct.h"
class CShanZhaiCorp :
    public CNewCorp
{
public:
    CShanZhaiCorp(IProduct *pproduct);
    ~CShanZhaiCorp(void);
    void MakeMoney();
};

ShanZhaiCorp.cpp

#include <stdio.h>
#include "ShanZhaiCorp.h"
#include <iostream>
using std::cout;
using std::endl;
CShanZhaiCorp::CShanZhaiCorp(IProduct *pproduct) : CNewCorp(pproduct)
{
}
CShanZhaiCorp::~CShanZhaiCorp(void)
{
}
void CShanZhaiCorp::MakeMoney()
{
    this->CNewCorp::MakeMoney();
    cout << "我赚钱呀..." << endl;
}

IProduct.h

#pragma once
class IProduct
{
public:
    IProduct(void)
    {
    }
    virtual ~IProduct(void)
    {
    }
    virtual void BeProducted() = 0;
    virtual void BeSelled() = 0;
};

House.h

#pragma once
#include "iproduct.h"
class CHouse :
    public IProduct
{
public:
    CHouse(void);
    ~CHouse(void);
    void BeProducted();
    void BeSelled();
};

House.cpp

#include <stdio.h>
#include "House.h"
#include <iostream>
using std::cout;
using std::endl;
CHouse::CHouse(void)
{
}
CHouse::~CHouse(void)
{
}
void CHouse::BeProducted()
{
    cout << "生产出的房子是这个样子的..." << endl;
}
void CHouse::BeSelled()
{
    cout << "生产出的房子卖出去了..." << endl;
}

Clothes.h

#pragma once
#include "iproduct.h"
class CClothes :
    public IProduct
{
public:
    CClothes(void);
    ~CClothes(void);
    void BeProducted();
    void BeSelled();
};

Clothes.cpp

#include <stdio.h>
#include "Clothes.h"
#include <iostream>
using std::cout;
using std::endl;
CClothes::CClothes(void)
{
}
CClothes::~CClothes(void)
{
}
void CClothes::BeProducted()
{
    cout << "生产出的衣服是这个样子的..." << endl;
}
void CClothes::BeSelled()
{
    cout << "生产出的衣服卖出去了..." << endl;
}

IPod.h

#pragma once
#include "iproduct.h"
class CIPod :
    public IProduct
{
public:
    CIPod(void);
    ~CIPod(void);
    void BeProducted();
    void BeSelled();
};

IPod.cpp

#include <stdio.h>
#include "IPod.h"
#include <iostream>
using std::cout;
using std::endl;
CIPod::CIPod(void)
{
}
CIPod::~CIPod(void)
{
}
void CIPod::BeProducted()
{
    cout << "生产出的ipod是这个样子的..." << endl;
}
void CIPod::BeSelled()
{
    cout << "生产出的ipod卖出去了..." << endl;
}

// Bridge.cpp : 定义控制台应用程序的入口点。

#include <stdio.h>
#include "NewHouseCorp.h"
#include "Clothes.h"
#include "IPod.h"
#include "ShanZhaiCorp.h"
#include <iostream>
using std::cout;
using std::endl;

void DoNewRun1()
{
    cout << "----------房地产公司是这样运行的----------" << endl;
    CHouse house;
    CNewHouseCorp newHouseCorp(&house);
    newHouseCorp.MakeMoney();
    cout << endl;

    cout << "----------山寨公司是这样运行的----------" << endl;
    CClothes clothes;
    CShanZhaiCorp shanZhaiCorp(&clothes);
    shanZhaiCorp.MakeMoney();
    cout << endl;
}

void DoNewRun2()
{
    cout << "----------房地产公司是这样运行的----------" << endl;
    CHouse house;
    CNewHouseCorp newHouseCorp(&house);
    newHouseCorp.MakeMoney();
    cout << endl;

    cout << "----------山寨公司是这样运行的----------" << endl;
    CIPod ipod;
    CShanZhaiCorp shanZhaiCorp(&ipod);
    shanZhaiCorp.MakeMoney();
    cout << endl;
}

int main()
{
    //只有两家公司,一家是房地产公司,另一家公司是衣服赚钱就生产衣服
    DoNewRun1();

    //只有两家公司,一家是房地产公司,另一家公司是ipod赚钱就生产ipod
    DoNewRun2();

    _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
    _CrtDumpMemoryLeaks();
    return 0;
}
----------房地产公司是这样运行的----------
生产出的房子是这个样子的...
生产出的房子卖出去了...
房地产公司赚大钱了...
----------山寨公司是这样运行的----------
生产出的衣服是这个样子的...
生产出的衣服卖出去了...
我赚钱呀...
----------房地产公司是这样运行的----------
生产出的房子是这个样子的...
生产出的房子卖出去了...
房地产公司赚大钱了...
----------山寨公司是这样运行的----------
生产出的ipod是这个样子的...
生产出的ipod卖出去了...
我赚钱呀...  

消息总线

什么是消息总线?

对象的关系之间一般有:依赖、关联、聚合、组合和继承,他们的耦合程度也是依次加强!大规模开发过程中,对象很多,关联关系很复杂,没有统一、简介的方法去管理对象的关系将会导致对象关系和蜘蛛网一样,或者循环依赖问题。
基于消息总线技术可以有效解决这些问题,对象通过消息联系而不是直接依赖或者关联。

消息总线的关键技术

  • 通用的消息类型
  • 消息注册
  • 消息分发

通用的消息定义

我们需要一种泛型的函数签名来定义成一个通用的消息格式。同时需要我们可以还需要定义一个主题类型,让订阅该主题的接受者接收此消息。
我们可以使用:std::function<Ret(Args…)>作为通用的函数签名。

消息的注册

总线内部维护了一个消息列表,当需要发送消息时,会遍历消息列表,从中查找是否有合适的消息和消息接收者,找到合适的接受者之后再次广播。
消息由:消息主题+泛型函数组成。topic + std::function<Ret(Args…)>这个泛型函数可能是所有的可调用对象,例如:普通函数、成员函数、函数对象、std::function和lambda表达式。消息的统一格式为std::function<Ret(Args…)>所以首先应该讲各种调用类型转换成该类型,格式统一后就可以将消息保存起来,以便后续分发(保存消息的方法见后面章节)。
接下来我们实现一个函数类型萃取的对下。

普通函数转换为std::function

//前置声明
template<typename T>
struct function_traits;

//普通函数
template<typename Ret, typename...Args>
struct function_traits<Ret(Args...)>
{
public:
    enum {arity = sizeof...(Args)};            //获取参数数量
    typedef Ret function_type(Args...);        //定义函数类型
    typedef Ret return_type;            
    using stl_function_type = std::function<function_type>;    //stl function类型  lambda可转换成stl function
    typedef Ret(*pointer)(Args...);

    template<size_t I>
    struct args
    {
        static_assert(I < arity, "index is out of range");
        //类似bind(_Binder) 源码实现,保存参数并且随时可用.
        using type = typename std::tuple_element<I, std::tuple<Args...>>::type;
    };
};

函数指针转换为std::function

函数指针,通常在C语言中经常使用,他的声明方式通常如下:

typedef void(*PFUNC)(int);

所以为了我们的函数类型萃取支持函数指针,我们需要将其返回值和入参提取出来。
具体实现如下:

//函数指针
template<typename Ret, typename...Args>
struct function_traits<Ret(*)(Args...)>
    : public function_traits<Ret(Args...)> {};

提取std::function类

这个就比较容易了,入参和返回值直接提取即可。

//std functional
template<typename Ret, typename...Args>
struct function_traits<std::function<Ret(Args...)>>
    : public function_traits<Ret(Args...)> {};

成员函数转换为std::function

这里需要特别注意的是,成员函数的调用一定是要有具体对象调用的。除非这个函数是静态函数(这个和普通函数类似)。所以我们需要函数类型和具体的调用对象。

//直接根据参数调用
template<typename ReturnType, typename ClassType, typename...Args>
void  help1(ReturnType(ClassType::*f)(Args...), ClassType& obj, Args&&...args)
{
    std::function<ReturnType(Args...)> func = [&obj, f, &args...](Args...) {
        return (obj.*f)(std::forward<Args>(args)...);
    };
    func(std::forward<Args>(args)...);
}

//返回可调用实体  此时Args可由具体调用时传入
template<typename ReturnType, typename ClassType, typename...Args>
std::function<ReturnType(Args...)>  help2(ReturnType(ClassType::*f)(Args...), ClassType& obj)
{
    std::function<ReturnType(Args...)> func = [&obj, f](Args&&...args) {
        return (obj.*f)(std::forward<Args>(args)...);
    };
    //func(std::forward<Args>(args)...);
    return func;
}

成员函数转换为std::function的更多细节

刚刚我们事先的成员函数虽然支持不同入参和返回类型,但是函数类型例如const类型的函数,并没有支持。接下里需要实现包含不同限定类型的函数。我们可使用宏定义的方式(此方法在标准库、STL库中多次被使用)实现。

//member functional
#define FUNCTION_TRAITS(...) \
template<typename ReturnType, typename ClassType, typename...Args> \
struct function_traits<ReturnType(ClassType::*)(Args...) __VA_ARGS__> : \
function_traits<ReturnType(Args...)>{}; \

FUNCTION_TRAITS();
FUNCTION_TRAITS(const);
FUNCTION_TRAITS(volatile);
FUNCTION_TRAITS(const volatile);

可以看到将const等类型扩展到函数限定符位置。

可调用对象转换为std::function

struct CallObject
{
    void operator()()
    {
        cout << "CallObject" << endl;
    }
};

//函数对象 模板实现时需要具体对象类型
template<typename Callable>
struct function_traits : function_traits<decltype(&Callable::operator())> {};

void testFunctionObject()
{
    auto f = to_function(CallObject());    //转换为std::function
    f();
}

将各类可调用对象转换为std::function函数实现

//转换成stl的function
template<typename Function>
typename function_traits<Function>::stl_function_type to_function(const Function& lambda)
{
    return static_cast<function_traits<Function>::stl_function_type>(lambda);
}
template<typename Function>
typename function_traits<Function>::stl_function_type to_function(Function&& lambda)
{
    return static_cast<function_traits<Function>::stl_function_type>(std::forward<Function>(lambda));
}

//转换成仿函数指针
template<typename Function>
typename function_traits<Function>::pointer to_function_pointer(const Function& lambda)
{
    return static_cast<function_traits<Function>::pointer>(lambda);
}

通过以上方式我们可以实现一个接受泛型类型的消息,接下里我们需要将各类消息保存起来,以便分发调用。
下面介绍消息保存和分发。

消息保存:由于消息类型有不同的返回值以及入参,这里可以使用之前介绍的Any作为消息载体
消息分发:这个就比较容易了,取出合适的函数对象(消息)直接调用即可

消息总线设计思想

消息总线融和了观察者和中介者模式,通过类型擦除擦除具体消息类型(Any)。观察者模式用来维护主题和适当的时候向观察者广播消息。中介者模式主要用来降低观察者模式互相依赖产生的耦合性。
消息总线维护的消息体是所有类型的可调用对象,没有对象之间的直接调用,更没有接口继承,主题和观察者仅仅是通过某种类型的消息联系起来,这个消息就是简单的返回值类型和入参。

下图是消息总线时序图,很好的说明的消息总线工作原理(来自原书)
消息总线时序图

其中主要的几个点就是:
1.观察者注册消息体
2.消息总线保存消息体
3.主题对象发送消息
4.消息总线调用合适主题的消息体
5.观察者收到消息并处理

完整的消息总线

class MessageBus
{
public:
    //注册消息
    template<typename F>
    void attach(F&& f, const string& topic = "")
    {
        auto func = to_function(std::forward<F>(f));
        add(topic, std::move(func));
    }

    //发送消息 没有参数
    template<typename R>
    void send(const string& topic = "")
    {
        using function_type = std::function<R()>;
        string strMsg = topic + typeid(function_type).name();
        auto range = m_map.equal_range(strMsg);
        for (auto iter = range.first; iter != range.second; ++iter)
        {
            auto f = iter->second.cast<function_type>();
            f();
        }
    }
    //发送消息 有参数
    template<typename R, typename... Args>
    void send(Args&&...args, const string& topic = "")
    {
        using function_type = std::function<R(Args...)>;
        string strMsg = topic + typeid(function_type).name();
        auto range = m_map.equal_range(strMsg);
        for (auto iter = range.first; iter != range.second; ++iter)
        {
            auto f = iter->second.cast<function_type>();
            f(std::forward<Args>(args)...);
        }
    }
    //移除某个主题 需要主题和消息类型
    template<typename R, typename... Args>
    void remove(const string& topic = "")
    {
        using function_type = std::function<R(Args...)>;
        string strMsg = topic + typeid(function_type).name();
        auto range = m_map.equal_range(strMsg);
        m_map.erase(range.first, range.second);
    }

private:
    template<typename F>
    void add(const string& topic, F&& f)
    {
        string strMsg = topic + typeid(F).name();
        m_map.emplace(std::move(strMsg), std::forward<F>(f));
    }

private:
    std::multimap<string, Any> m_map;
};

测试代码如下:

MessageBus g_bus;
string g_topic = "drive";    //主题类型
struct Subject
{
    //主题对象发送某种消息,
    void send(const string& topic)
    {
        g_bus.send<void, int>(50, topic);
    }
};

struct Car
{
    Car()
    {
        //注册到消息总线
        g_bus.attach([this](int speed) {drive(speed); }, g_topic);
    }
    void drive(int speed)
    {
        //观察者对象接收到某种消息的响应体(lambda封装)
        cout << "car drive:" << speed << endl;
    }
};

struct Bus
{
    Bus()
    {
        //注册到消息总线
        g_bus.attach([this](int speed) {drive(speed); }, g_topic);
    }
    void drive(int speed)
    {
        //观察者对象接收到某种消息的响应体(lambda封装)
        cout << "bus drive:" << speed << endl;
    }
};

void testBus()
{
    Subject subject;
    Car car;
    Bus bus;
    subject.send(g_topic);
    cout << "---------------" << endl;
    subject.send("");
}

不出所料,观察者Car和Bus接收到主题”drive”消息,由消息体触发drive函数调用。

复杂的对象关系梳理
我们上面实现的仅仅是简单的发送主题,然后响应。如果我们希望,观察者受到消息后,可以进行“回复”,这时候消息总线的优势就更一步体现了,我们只需重新注册一种主题即可。

MessageBus g_bus;
string g_topic = "drive";    //主题类型
string g_callbacktopic = "driveok";
struct Subject
{
    Subject()
    {
        g_bus.attach([this]{driveok(); }, g_callbacktopic);
    }

    void send(const string& topic)
    {
        g_bus.send<void, int>(50, topic);
    }

    void driveok()
    {
        cout << "driveok" << endl;
    }
};

struct Car
{
    Car()
    {
        //注册到消息总线
        g_bus.attach([this](int speed) {drive(speed); }, g_topic);
    }
    void drive(int speed)
    {
        cout << "car drive:" << speed << endl;
        //额外增加处理函数
        g_bus.send<void>(g_callbacktopic);
    }
};

struct Bus
{
    Bus()
    {
        //注册到消息总线
        g_bus.attach([this](int speed) {drive(speed); }, g_topic);
    }
    void drive(int speed)
    {
        cout << "bus drive:" << speed << endl;
    }
};

void testBus()
{
    Subject subject;
    Car car;
    Bus bus;
    subject.send(g_topic);
    cout << "---------------" << endl;
    subject.send("");
}

可以看到,Car注册了回复主题,在执行完成后,通知消息总线即可实现“回复”功能。

思考:
其实我们可将消息总线和状态机结合一下,当处于某种状态执行某些操作,然后此操作完成后可以选择继续执行某些操作,这些操作可以是不同的主题类型。
消息总线将复杂对象关系简化了,降低了对象关系的复杂度和耦合度,但是也要注意消息总线的使用场景,对象关系很简单的时候使用,反而将系统变的很复杂,在对象关系多且复杂的场景,消息总线才能更好的发挥作用。

个人总结:
消息总线的思想是总线接管所有消息处理逻辑,因此总线需要将所有函数格式化为统一接口,格式化时需要传入被调用函数的地址,被调用函数的参数类型,被调用函数的参数(数据).

注意:
消息总线案例不完美,需要增加多个发布者,同时解耦总线和发布者,而不是搞成一个。

回调模式

回调函数的简单代码实现如下:

public class ConcretSubject {
   private Callback callback;

   public void register(Callback callback) {
       this.callback = callback;
   }

   public void call() {
       callback.onCall();
   }
}
public interface Callback {
   void onCall();
}
public class Main {

   public static void main(String[] args) {
       ConcretSubject subject = new ConcretSubject();
       Callback callback = new Callback() {
           @Override
           public void onCall() {
               System.out.println("call");
           }
       };
       subject.register(callback);
       subject.call();
   }
}

通过对比,我们发现,观察者模式和回调函数模式及其相似,差别仅在于在观察者模式中,被观察者维护这一个观察者列表,而在回调模式中,“被观察者”只是保存了一个“观察者”。这就是形式上的终极区别。

也就是说,回调函数是一种特殊的观察者模式,是一种一对一的观察者模式。

参考链接:
https://www.cnblogs.com/cbf4life/
https://www.cnblogs.com/wanggary/archive/2011/04/07/2008796.html
https://www.cnblogs.com/cbf4life/
https://www.cnblogs.com/wanggary/archive/2011/04/07/2008796.html
https://blog.csdn.net/xufeng0991/article/details/50267675


文章作者: 陈德强
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 陈德强 !
¥
  目录