C++学习笔记之设计模式

  1. 设计模式的概述
    设计模式的定义:设计模式是在特定环境下人们解决某类重复出现的一套成功或有效的解决方案。
    设计模式有什么用?
    从高端来讲的话,作用大了去了。(网上是这么说的,虽然我还体会不到哈哈)那么对于初学者来说,学习设计模式将有助于更深入的理解面向对象思想,让你知道:
    1、如何将代码分散在不同的类中?
    2、为什么要有“接口”?
    3、什么是对抽象编程?
    4、何时不应该使用继承?
    5、如何不修改源代码增加新功能?
    6、更好的阅读和理解现有类库与其他系统中的源代码。
  2. 面向对象设计原则
    如何同时提高一个软件系统的可维护性和可复用性是面向对象设计需要解决的核心问题之一。面向对象设计原则为支持可维护性复用而诞生,这些原则蕴含在很多设计模式中,它们是从许多设计方案中总结出的指导性原则。
    2.1面向对象设计原则表
    单一职责原则:类的职责单一,对外只提供一种功能,而引起类变化的原因都应该只有一个。
    开闭原则:类的改动是通过增加代码进行的,而不是修改代码。
    里氏代换原则:任何抽象类出现的地方都可以用他的实现类进行替换,实际就是虚拟机制,语言级别实现面向对象功能。(多态)
    依赖倒转原则:依赖于抽象(接口),不要依赖具体的实现(类),也就是针对接口编程。
    接口隔离原则:不应该强迫用户的程序依赖他们不需要的接口方法。一个接口应该只提供一种对外功能,不应该把所有操作都封装到一个接口中去。
    合成复用原则:如果使用继承,会导致父类的任何变换都可能影响到子类的行为。如果使用对象组合,就降低了这种依赖关系。对于继承和组合,优先使用组合。(组合的意思就是:类A和类B,在类B中将类A实例化,从而使用类A中的方法,而不是用类B去继承类A)
    迪米特法则:一个对象应该对其他对象尽可能少的了解,从而降低各个对象之间的耦合,提高系统的可维护性。例如在一个程序中,各个模块之间相互调用时,通常会提供一个统一的接口来实现。这样其它模块就不需要了解另外一个模块的内部实现细节,这样当一个模块内部的实现发生改变时,不会影响其它模块的使用。
    2.1.1开闭原则案例
    对扩展开放,对修改关闭,增加功能是通过增加代码来实现,而不是去修改源代码。
    例如下面是一个计算器的代码,这样写简单明了,但是如果想增加功能就必须修改getResult函数,这样容易导致出错。
class Calculate{
public:
    Calculate(int a, int b, string moperate){
        this->m_a = a;
        this->m_b = b;
        this->m_operator = moperate;
    }
    int getResult(){
        if(m_operator.compare("+") == 0){
            return m_a + m_b;
        }
        else if(m_operator.compare("-") == 0){
            return m_a - m_b;
        }
        else if(m_operator.compare("*") == 0){
            return m_a * m_b;
        }
        else if(m_operator.compare("/") == 0){
            return m_a / m_b;
        }
    }
private:
    int m_a;
    int m_b;
    string m_operator;
    int m_ret;
};
void test(){
    Calculate* cal = new Calculate(10,20,"+");
    cout << cal->getResult() << endl;
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    test();
    return a.exec();
}

例如下面的代码,如果要再增加其他运算,则再添加一个类继承抽象类AbstractCalculate,就不用修改代码减少代码出错的可能性。

//写一个抽象类
class AbstractCalculate{
public:
    virtual int getResult() = 0;
    virtual void setOperatorNumber(int a,int b) = 0;
};

//加法计算器类
class PlusCalculate : public AbstractCalculate{
public:
    virtual void setOperatorNumber(int a,int b){
        this->mA = a;
        this->mB = b;
    }
    virtual int getResult(){
        return mA + mB;
    }
    ~PlusCalculate(){
    
    }
public:
    int mA;
    int mB;
};

//减法计算器类
class MinuteCalculate : public AbstractCalculate{
public:
    virtual void setOperatorNumber(int a,int b){
        this->mA = a;
        this->mB = b;
    }
    virtual int getResult(){
        return mA - mB;
    }
public:
    int mA;
    int mB;
};

//乘法计算器类
class MultiplyCalculate : public AbstractCalculate{
public:
    virtual void setOperatorNumber(int a,int b){
        this->mA = a;
        this->mB = b;
    }
    virtual int getResult(){
        return mA * mB;
    }
public:
    int mA;
    int mB;
};

//除法计算器类
class DivideCalculate : public AbstractCalculate{
public:
    virtual void setOperatorNumber(int a,int b){
        this->mA = a;
        this->mB = b;
    }
    virtual int getResult(){
        return mA / mB;
    }
public:
    int mA;
    int mB;
};

void test(){
    AbstractCalculate* cal = new PlusCalculate();
    cal->setOperatorNumber(10,20);
    cout << cal->getResult() << endl;
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    test();
    return a.exec();
}

2.1.2迪米特法则案例
当在开发子系统时,其他要调用你的系统时,不要把细节暴露给其他系统,只需要给它一个接口就可以。例如下面的案例,要买高品质的楼盘,不要我们一个个楼盘的去找,而是提供一个中介的接口给客户,让中介去找,客户只需要提供给中介找房的要求即高品质就行。

//迪米特法则,又叫最少知识原则

class AbstractBuilding{
public:
    virtual void sale() = 0;
    virtual string getQuality() = 0;
};

//楼盘A
class BuildingA : public AbstractBuilding{
public:
    virtual void sale(){
        mQuality = "高品质";
        cout << "楼盘A" << mQuality << "is saled" << endl;
    }
    virtual string getQuality(){
        return mQuality;
    }
public:
    string mQuality;
};

//楼盘B
class BuildingB : public AbstractBuilding{
public:
    virtual void sale(){
        mQuality = "低品质";
        cout << "楼盘B" << mQuality << "is saled" << endl;
    }
    virtual string getQuality(){
        return mQuality;
    }
public:
    string mQuality;
};
//中介类
class Mediator{
public:
    Mediator(){
        AbstractBuilding* building = new BuildingA;
        vBuilding.push_back(building);
        building = new BuildingB;
        vBuilding.push_back(building);
    }
    //对外提供接口
    AbstractBuilding* findMyBuilding(string quality){
        vector<AbstractBuilding*>::iterator it;
        for(it= vBuilding.begin();it != vBuilding.end();it++)
        {
            if((*it)->getQuality() == quality)
            {
                return *it;
            }
        }
        return NULL;
    }
    ~Mediator(){
        for(vector<AbstractBuilding*>::iterator it = vBuilding.begin();it != vBuilding.end();it ++)
        {
            if(*it != NULL)
            {
                delete *it;
            }
        }
    }
public:
    vector<AbstractBuilding*> vBuilding;
};

//客户端
void test(){
    Mediator* mediator = new Mediator;
    AbstractBuilding* building = mediator->findMyBuilding("高品质");
    if(building != NULL)
    {
        building->sale();
    }
    else{
        cout << "没有符号您的楼盘" << endl;
    }
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    test();
    return a.exec();
}

2.1.3合成复用原则案例

//抽象车
class AbstractCar{
public:
    virtual void run() = 0;
};

//大众车
class Dazhong :public AbstractCar{
public:
    virtual void run(){
        cout << "大众车启动。。。" << endl;
    }
};

//拖拉机
class Tuolaji :public AbstractCar{
public:
    virtual void run(){
        cout << "拖拉机启动..." << endl;
    }
};

//两个Person类都针对具体类,用继承时每调用一次车都要增加一个类,所以不适用继承
//class Person :public Tuolaji{
//public:
//    void Doufeng(){
//        run();
//    }
//};
//class Person :public Dazhong{
//public:
//    void Doufeng(){
//        run();
//    }
//};

//可以使用组合
class Person{
public:
    void setCar(AbstractCar* car){
        this->car = car;
    }
    void Doufeng(){
        this->car->run();
        if(this->car != NULL){
            delete this->car;
        }
    }
public:
    AbstractCar* car;
};

void test(){
    Person* p = new Person;
    p->setCar(new Dazhong);
    p->Doufeng();

    p->setCar(new Tuolaji);
    p->Doufeng();
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    test();
    return a.exec();
}

2.1.4依赖倒转原则案例
C++学习笔记之设计模式

class BankWorker{
public:
    void saveService(){
        cout << "办理存款业务" << endl;
    }
    void payService(){
        cout << "办理支付业务" << endl;
    }
    void transformService(){
        cout << "办理转账业务" << endl;
    }
};

//中层模块
void doSaveBusiness(BankWorker* worker){
    worker->saveService();
}
void doPayBusiness(BankWorker* worker){
    worker->payService();
}
void doTransformBusiness(BankWorker* worker){
    worker->transformService();
}

void test(){
    BankWorker* worker = new BankWorker;
    doSaveBusiness(worker);
    doPayBusiness(worker);
    doTransformBusiness(worker);
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    test();
    return a.exec();
}

C++学习笔记之设计模式

class AbstractWorker{
public:
    virtual void doBusiness() = 0;
};

//专门负责办理存款业务的工作人员
class SaveBankerWorker : public AbstractWorker{
public:
    virtual void doBusiness(){
        cout << "办理存款业务" << endl;
    }
};

//专门负责办理支付业务的工作人员
class PayBankerWorker : public AbstractWorker{
public:
    virtual void doBusiness(){
        cout << "办理支付业务" << endl;
    }
};

//专门负责办理转账业务的工作人员
class TransformBankerWorker : public AbstractWorker{
public:
    virtual void doBusiness(){
        cout << "办理转账业务" << endl;
    }
};

//中层业务
void doBusiness(AbstractWorker* worker){
    worker->doBusiness();
    delete worker;
}

void test(){

    doBusiness(new SaveBankerWorker);
    doBusiness(new PayBankerWorker);
    doBusiness(new TransformBankerWorker);
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    test();
    return a.exec();
}

3.创建型模型
3.1简单工厂模式
C++学习笔记之设计模式
适用场景:1.工厂类负责创建的对象比较少,由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。
2.客户端只知道传入工厂类的参数,对于如何创建对象并不关心。

//抽象水果
class AbstractFruit{
public:
    virtual void ShowName() = 0;
};

//苹果
class Apple : public AbstractFruit{
public:
    virtual void ShowName(){
        cout << "我是苹果" << endl;
    }
};

//香蕉
class Banana : public AbstractFruit{
public:
    virtual void ShowName(){
        cout << "我是香蕉" << endl;
    }
};

//鸭梨
class Pear : public AbstractFruit{
public:
    virtual void ShowName(){
        cout << "我是鸭梨" << endl;
    }
};

//水果工厂
class FruitFactory{
public:
    static AbstractFruit* CreateFruit(string flag){
        if(flag == "apple"){
            return new Apple;
        }
        else if(flag == "banana"){
            return new Banana;
        }
        else if(flag == "pear"){
            return new Pear;
        }
        else{
            return NULL;
        }
    }
};

void test(){
    //不需要关心怎么创建哪个类的对象,只管传参数
    FruitFactory* factory = new FruitFactory;
    AbstractFruit* fruit = factory->CreateFruit("apple");
    fruit->ShowName();
    delete fruit;

    fruit = factory->CreateFruit("banana");
    fruit->ShowName();
    delete fruit;

    fruit = factory->CreateFruit("pear");
    fruit->ShowName();
    delete fruit;

    delete factory;
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    test();
    return a.exec();
}

3.2工厂方法模式
上面讲到简单工厂模式,不符合开闭原则,追其原因,就在Factory中。如果将Factory 抽象出来就可以解决这个问题。简单工厂模式+“开闭原则”=工厂方法模式。C++学习笔记之设计模式
使用场景:1.客户端不知道它所需要的对象的类。
2.抽象工厂类通过其子类来指定创建哪个对象。

//抽象水果
class AbstractFruit{
public:
    virtual void ShowName() = 0;
};
//苹果
class Apple : public AbstractFruit{
public:
    virtual void ShowName(){
        cout << "我是苹果" << endl;
    }
};
//香蕉
class Banana : public AbstractFruit{
public:
    virtual void ShowName(){
        cout << "我是香蕉" << endl;
    }
};
//鸭梨
class Pear : public AbstractFruit{
public:
    virtual void ShowName(){
        cout << "我是鸭梨" << endl;
    }
};

//抽象工厂
class AbstractFruitFactory{
public:
    virtual AbstractFruit* CreateFruit() = 0;
};
//苹果工厂
class AppleFactory : public AbstractFruitFactory{
public:
    virtual AbstractFruit* CreateFruit(){
        return new Apple;
    }
};
//香蕉工厂
class BananaFactory : public AbstractFruitFactory{
public:
    virtual AbstractFruit* CreateFruit(){
        return new Banana;
    }
};
//鸭梨工厂
class PearFactory : public AbstractFruitFactory{
public:
    virtual AbstractFruit* CreateFruit(){
        return new Pear;
    }
};


void test(){
    AbstractFruitFactory* factory = NULL;
    AbstractFruit* fruit = NULL;

    //创建一个苹果工厂
    factory = new AppleFactory;
    fruit = factory->CreateFruit();
    fruit->ShowName();
    delete factory;
    delete fruit;

    //创建一个香蕉工厂
    factory = new BananaFactory;
    fruit = factory->CreateFruit();
    fruit->ShowName();
    delete factory;
    delete fruit;

    //创建一个鸭梨工厂
    factory = new PearFactory;
    fruit = factory->CreateFruit();
    fruit->ShowName();
    delete factory;
    delete fruit;

}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    test();
    return a.exec();
}

3.3抽象工厂模式
C++学习笔记之设计模式

//抽象苹果
class AbstractApple{
public:
    virtual void ShowName() = 0;
};
//中国苹果
class ChinaApple : public AbstractApple{
public:
    virtual void ShowName(){
        cout << "中国苹果" << endl;
    }
};
//美国苹果
class AmeracaApple : public AbstractApple{
public:
    virtual void ShowName(){
        cout << "美国苹果" << endl;
    }
};
//倭国苹果
class JapanApple : public AbstractApple{
public:
    virtual void ShowName(){
        cout << "倭国苹果" << endl;
    }
};

//抽象香蕉
class AbstractBanana{
public:
    virtual void ShowName() = 0;
};
//中国香蕉
class ChinaBanana : public AbstractBanana{
public:
    virtual void ShowName(){
        cout << "中国香蕉" << endl;
    }
};
//美国香蕉
class AmeracaBanana : public AbstractBanana{
public:
    virtual void ShowName(){
        cout << "美国香蕉" << endl;
    }
};
//倭国香蕉
class JapanBanana : public AbstractBanana{
public:
    virtual void ShowName(){
        cout << "倭国香蕉" << endl;
    }
};

//抽象鸭梨
class AbstractPear{
public:
    virtual void ShowName() = 0;
};
//中国鸭梨
class ChinaPear : public AbstractPear{
public:
    virtual void ShowName(){
        cout << "中国鸭梨" << endl;
    }
};
//美国鸭梨
class AmeracaPear : public AbstractPear{
public:
    virtual void ShowName(){
        cout << "美国鸭梨" << endl;
    }
};
//倭国鸭梨
class JapanPear : public AbstractPear{
public:
    virtual void ShowName(){
        cout << "倭国鸭梨" << endl;
    }
};

//抽象工厂  针对产品族
class AbstractFactory{
public:
    virtual AbstractApple* CreateApple() = 0;
    virtual AbstractBanana* CreateBanana() = 0;
    virtual AbstractPear* CreatePear() = 0;
};
//中国工厂
class ChinaFactory : public AbstractFactory{
public:
    virtual AbstractApple* CreateApple(){
        return new ChinaApple;
    }
    virtual AbstractBanana* CreateBanana(){
        return new ChinaBanana;
    }
    virtual AbstractPear* CreatePear(){
        return new ChinaPear;
    }
};
//美国工厂
class AmerecaFactory : public AbstractFactory{
public:
    virtual AbstractApple* CreateApple(){
        return new AmeracaApple;
    }
    virtual AbstractBanana* CreateBanana(){
        return new AmeracaBanana;
    }
    virtual AbstractPear* CreatePear(){
        return new AmeracaPear;
    }
};
//倭国工厂
class JapanFactory : public AbstractFactory{
public:
    virtual AbstractApple* CreateApple(){
        return new JapanApple;
    }
    virtual AbstractBanana* CreateBanana(){
        return new JapanBanana;
    }
    virtual AbstractPear* CreatePear(){
        return new JapanPear;
    }
};

void test(){
    AbstractFactory* factory = NULL;
    AbstractApple* apple = NULL;
    AbstractBanana* banana = NULL;
    AbstractPear* pear = NULL;

    factory = new ChinaFactory;
    apple = factory->CreateApple();
    banana = factory->CreateBanana();
    pear = factory->CreatePear();
    apple->ShowName();
    banana->ShowName();
    pear->ShowName();
    delete pear;
    delete banana;
    delete apple;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    test();
    return a.exec();
}

3.4单例模式
一个系统中只能有一个类型的对象。

//实现单例步骤
//1. 构造函数私有化(为了不能在外面使用实例化或者new对象,因为实例化和new都会调用构造函数)
//2. 增加静态私有的当前类的指针变量(静态函数只能访问静态的指针变量)
//3. 提供静态对外接口,可以让用户获得单例对象(静态函数或者变量可以通过类名::调用)

//单例分为懒汉式
class Singleton_lazy{
private:
    Singleton_lazy(){}
public:
    static Singleton_lazy* getInstance(){
        if(pSingleton == NULL){
            pSingleton = new Singleton_lazy;
        }
        return pSingleton;
    }
private:
    static Singleton_lazy* pSingleton;
};
//类外初始化
Singleton_lazy* Singleton_lazy::pSingleton = NULL;

//饿汉式
class Singleton_hungry{
private:
    Singleton_hungry(){
        cout << "我是饿汉式" <<endl;
    }
public:
    static Singleton_hungry* getInstance(){
        return pSingleton;
    }
private:
    static Singleton_hungry* pSingleton;
};
Singleton_hungry* Singleton_hungry::pSingleton = new Singleton_hungry;

void test(){
    Singleton_lazy* p1 = Singleton_lazy::getInstance();
    Singleton_lazy* p2 = Singleton_lazy::getInstance();
    if(p1 == p2){
        cout << "两个指针指向同一块内存,是单例" << endl;
    }
    else{
        cout << "不是单例" << endl;
    }

    Singleton_hungry* p3 = Singleton_hungry::getInstance();
    Singleton_hungry* p4 = Singleton_hungry::getInstance();
    if(p3 == p4){
        cout << "两个指针指向同一块内存,是单例" << endl;
    }
    else{
        cout << "不是单例" << endl;
    }
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    cout << "我是main函数" << endl;
    test();
    return a.exec();
}
//运行结果:我是饿汉式 我是main函数 两个指针指向同一块内存,是单例 两个指针指向同一块内存,是单例
//从中可以看出饿汉式在main函数执行前就已经执行了,所以叫饿汉式
//第一个Singleton会进入if条件里面,而第二个直接跳过,从而实现单例

4.结构型模式
4.1代理模式
代理模式定义:**为其他对象提供一种代理以控制对这个对象的访问。**在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

//以下例子就是为MySystem类的对象提供MySystemProxy代理来控制对这个对象的访问
class AbstractCommonInterface{
public:
    virtual void run() = 0;
};

//系统已经写好,但是必须要有权限,不能所有人都来启动我的系统。
class MySystem : public AbstractCommonInterface{
public:
    virtual void run(){
        cout << "系统启动" << endl;
    }
};
//所以只能只能通过代理类来启动,要提供用户名和密码
class MySystemProxy : public AbstractCommonInterface{
public:
    MySystemProxy(string username,string password){
        this->mUsername = username;
        this->mPassword = password;
        pSystem = new MySystem;
    }

    bool checkUsernameAndPassword(){
        if(mUsername == "admin" && mPassword == "admin"){
            return true;
        }
        return false;
    }
    virtual void run(){
        if(checkUsernameAndPassword()){
            cout << "用户名和密码正确,验证通过" << endl;
            this->pSystem->run();
        }
        else{
            cout << "用户名或者密码错误,权限不足" << endl;
        }
    }
    ~MySystemProxy(){
        if(pSystem != NULL){
            delete pSystem;
        }
    }
public:
    MySystem* pSystem;
    string mUsername;
    string mPassword;
};

void test(){
    MySystemProxy* proxy = new MySystemProxy("admin","admin");
    proxy->run();
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    test();
    return a.exec();
}

4.2外观模式
外观模式就是将复杂的子系统抽象到同一个的接口进行管理,外界只需要通过此接口与子类系统进行交互,而不必要直接与复杂的子系统进行交互。

//电视机
class Television{
public:
    void On(){
        cout << "电视机打开。。" << endl;
    }
    void Off(){
        cout << "电视机关闭。。" << endl;
    }
};
//灯
class Light{
public:
    void On(){
        cout << "灯打开。。" << endl;
    }
    void Off(){
        cout << "灯关闭。。" << endl;
    }
};
//音响
class Audio{
public:
    void On(){
        cout << "音响打开。。" << endl;
    }
    void Off(){
        cout << "音响关闭。。" << endl;
    }
};
//麦克风
class Microphone{
public:
    void On(){
        cout << "麦克风打开。。" << endl;
    }
    void Off(){
        cout << "麦克风关闭。。" << endl;
    }
};
//DVD播放器
class DVDPlayer{
public:
    void On(){
        cout << "DVD播放器打开。。" << endl;
    }
    void Off(){
        cout << "DVD播放器关闭。。" << endl;
    }
};
//游戏机
class Gamemachine{
public:
    void On(){
        cout << "游戏机打开。。" << endl;
    }
    void Off(){
        cout << "游戏机关闭。。" << endl;
    }
};

class KTVMode{
public:
    KTVMode(){
        pTV = new Television;
        pLight = new Light;
        pAudio = new Audio;
        pMicrophone = new Microphone;
        pDvd = new DVDPlayer;
    }
    ~KTVMode(){
        delete pTV;
        delete pLight;
        delete pAudio;
        delete pMicrophone;
        delete pDvd;
    }
    void OnKtv(){
        pTV->On();
        pLight->Off();
        pAudio->On();
        pMicrophone->On();
        pDvd->On();
    }
    void OffKtv(){
        pTV->Off();
        pLight->On();
        pAudio->Off();
        pMicrophone->Off();
        pDvd->Off();
    }
public:
    Television* pTV;
    Light* pLight;
    Audio* pAudio;
    Microphone* pMicrophone;
    DVDPlayer* pDvd;
};

void test(){
    KTVMode* ktv = new KTVMode;
    ktv->OnKtv();
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    test();
    return a.exec();
}

4.3适配器模式

//适配器模式 就是将已经写好的接口,但是这个接口不符合需求
//将写好的接口转换成目标接口

//这个函数我已经写好
struct MyPrint{
    void operator()(int v1,int v2){
        cout << v1 + v2 << endl;
    }
};

//定义目标接口  我要是配偶  适配成什么样的
class Target{
    virtual void operator()(int v) = 0;
};

//写适配器
class Adapter : public Target{
public:
    Adapter(int param){
        this->param = param;
    }
    virtual void operator()(int v){
        print(v,param);
    }
public:
    MyPrint print;
    int param;
};

//MyBing2nd
Adapter MyBind2nd(int v){
    return Adapter(v);
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    vector<int>v;
    for(int i = 0; i < 10; i++){
        v.push_back(i);
    }
    for_each(v.begin(),v.end(),MyBind2nd(10));
    return a.exec();
}

4.4装饰模式
装饰模式又叫包装模式,通过一种对客户端的方式来扩展对象功能,是继承关系的一种替代。
5.行为型模式
用来对类或对象怎样交互和怎样分配职责进行描述。

//一般情况下,用继承实现类的扩展
//装饰模式,可以动态给一个类增加功能

//抽象英雄
class AbstractHero{
public:
    virtual void ShowStatus() = 0;
public:
    int mHp;
    int mMp;
    int mAt;
    int mDf;
};
//具体英雄A
class HeroA : public AbstractHero{
public:
    HeroA(){
        mHp = 0;
        mMp = 0;
        mAt = 0;
        mDf = 0;
    }
    virtual void ShowStatus(){
        cout << "血量:" << mHp << endl;
        cout << "魔法:" << mMp << endl;
        cout << "攻击:" << mAt << endl;
        cout << "防御:" << mDf << endl;
    }
};

//英雄穿上某个装饰物,那么它还是个英雄,但是不是之前的英雄,也具有之前英雄的属性
class AbstractEquipment : public AbstractHero{
public:
    AbstractEquipment(AbstractHero* hero){
        this->pHero = hero;
    }
    virtual void ShowStatus(){

    }
public:
    AbstractHero* pHero;
};

//狂徒
class KuangtuEquipment : public AbstractEquipment{
public:
    KuangtuEquipment(AbstractHero* hero) :AbstractEquipment(hero){//调用父类构造函数完成初始化

    }
    //增加额外功能
    void AddKuangtu(){
        cout << "英雄穿上狂徒之后。。" << endl;
        this->mHp = this->pHero->mHp;
        this->mMp = this->pHero->mMp;
        this->mAt = this->pHero->mAt;
        this->mDf = this->pHero->mDf + 30;

        delete this->pHero;
    }
    virtual void ShowStatus(){
        AddKuangtu();
        cout << "血量:" << mHp << endl;
        cout << "魔法:" << mMp << endl;
        cout << "攻击:" << mAt << endl;
        cout << "防御:" << mDf << endl;
    }
};
//无尽之刃
class WujinzhiKnife : public AbstractEquipment{
public:
    WujinzhiKnife(AbstractHero* hero) :AbstractEquipment(hero){//调用父类构造函数完成初始化

    }
    //增加额外功能
    void AddWujinzhiKnife(){
        cout << "英雄装备无尽之刃之后。。" << endl;
        this->mHp = this->pHero->mHp;
        this->mMp = this->pHero->mMp;
        this->mAt = this->pHero->mAt + 80;
        this->mDf = this->pHero->mDf;

        delete this->pHero;
    }
    virtual void ShowStatus(){
        AddWujinzhiKnife();
        cout << "血量:" << mHp << endl;
        cout << "魔法:" << mMp << endl;
        cout << "攻击:" << mAt << endl;
        cout << "防御:" << mDf << endl;
    }
};

void test(){
    AbstractHero* hero = new HeroA;
    hero->ShowStatus();
    cout << "----------------" << endl;

    //给裸奔的衣服穿上狂徒之后
    hero = new KuangtuEquipment(hero);
    hero->ShowStatus();

    //给英雄装备武器
    hero = new WujinzhiKnife(hero);
    hero->ShowStatus();
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    test();
    return a.exec();
}

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

class DrinkTemplate{
public:
    //煮水
    virtual void BoildWater() = 0;
    //冲泡
    virtual void Brew() = 0;
    //倒入杯中
    virtual void PourCup() = 0;
    //加辅助材料
    virtual void AddSomething() = 0;

    //模板方法
    void Make(){
        BoildWater();
        Brew();
        PourCup();
        AddSomething();
    }
};

//冲泡咖啡
class Coffee : public DrinkTemplate{
public:
    virtual void BoildWater(){
        cout << "煮山泉水。。" << endl;
    }
    virtual void Brew(){
        cout << "冲泡咖啡。。" << endl;
    }
    virtual void PourCup(){
        cout << "咖啡倒入杯中。。" << endl;
    }
    virtual void AddSomething(){
        cout << "加糖,加牛奶。。" << endl;
    }
};

//冲泡茶水
class Tea : public DrinkTemplate{
public:
    virtual void BoildWater(){
        cout << "煮蒸馏水。。" << endl;
    }
    virtual void Brew(){
        cout << "冲泡铁观音。。" << endl;
    }
    virtual void PourCup(){
        cout << "茶水倒入杯中。。" << endl;
    }
    virtual void AddSomething(){
        cout << "加柠檬。。" << endl;
    }
};
void test(){
    DrinkTemplate* tea = new Tea;
    tea->Make();
    cout << "-------------------" << endl;
    DrinkTemplate* coffee = new Coffee;
    coffee->Make();
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    test();
    return a.exec();
}

优点:(1)在父类中形式化的定义一个算法,而由它的子类来实现细节的处理,在子类实现详细的处理算法时并不会改变算法中步骤的执行顺序。
(2)模板方法模式是一种代码复用技术,它在类库设计中尤为重要,它提取了类库中的公共行为,将公共行为放在父类中,而通过其子类来实现不同的行为,它鼓励我们恰当使用继承来实现代码复用。
(3)在模板方法模式中可以通过子类来覆盖父类的基本方法,不同的子类可以提供基本方法的不同实现,更换和增加新的子类很方便,符合单一职责原则和开闭原则。
5.2策略模式
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使它的客户而独立变化。

//抽象武器策略
class WeaponStrategy{
public:
    virtual void UseWeapon() = 0;
};

class Knife : public WeaponStrategy{
public:
    virtual void UseWeapon(){
        cout << "使用匕首!" << endl;
    }
};
class AK47 : public WeaponStrategy{
public:
    virtual void UseWeapon(){
        cout<< "使用AK47!" << endl;
    }
};
class Character{
public:
    void setWeapon(WeaponStrategy* Weapon){
        this->pWeapon = Weapon;
    }
    void ThrowWeapon(){
        this->pWeapon->UseWeapon();
    }
public:
    WeaponStrategy* pWeapon;
};

void test(){
    //创建角色
    Character* character = new Character;

    //武器策略
    WeaponStrategy* knife = new Knife;
    WeaponStrategy* ak47 = new AK47;

    character->setWeapon(knife);
    character->ThrowWeapon();

    character->setWeapon(ak47);
    character->ThrowWeapon();

    delete knife;
    delete ak47;
    delete character;
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    test();
    return a.exec();
}

5.3命令模式

//协议处理类
class HandleClientProtocol{
public:
    //处理增加金币
    void AddMoney(){
        cout << "给玩家增加金币" << endl;
    }
    //处理增加钻石
    void AddDiamond(){
        cout << "给玩家增加钻石" << endl;
    }
    //处理玩家装备
    void AddEquipment(){
        cout << "给玩家穿装备" << endl;
    }
    //处理玩家升级
    void addLevel(){
        cout << "给玩家升级" << endl;
    }
};

//命令接口
class AbstractCommand{
public:
    virtual void handle() = 0;
};

//处理增加金币请求
class AddMoneyCommand : public AbstractCommand{
public:
    AddMoneyCommand(HandleClientProtocol* protocol){
        this->pProtocol = protocol;
    }
    virtual void handle(){
        this->pProtocol->AddMoney();
    }
public:
    HandleClientProtocol* pProtocol;
};
//处理增加钻石请求
class AddDiamondCommand : public AbstractCommand{
public:
    AddDiamondCommand(HandleClientProtocol* protocol){
        this->pProtocol = protocol;
    }
    virtual void handle(){
        this->pProtocol->AddDiamond();
    }
public:
    HandleClientProtocol* pProtocol;
};
//处理穿装备请求
class AddEquipnentCommand : public AbstractCommand{
public:
    AddEquipnentCommand(HandleClientProtocol* protocol){
        this->pProtocol = protocol;
    }
    virtual void handle(){
        this->pProtocol->AddEquipment();
    }
public:
    HandleClientProtocol* pProtocol;
};
//处理升级请求
class AddLevelCommand : public AbstractCommand{
public:
    AddLevelCommand(HandleClientProtocol* protocol){
        this->pProtocol = protocol;
    }
    virtual void handle(){
        this->pProtocol->addLevel();
    }
public:
    HandleClientProtocol* pProtocol;
};
//服务器程序
class Server{
public:
    void addRequest(AbstractCommand* command){
        mCommand.push(command);
    }
    void startHandle(){
        while(!mCommand.empty()){
            Sleep(2000);
            AbstractCommand* command = mCommand.front();
            command->handle();
            mCommand.pop();
        }
    }
public:
    queue<AbstractCommand*> mCommand;
};

void test(){
    HandleClientProtocol* protocol = new HandleClientProtocol;
    //客户端增加金币的请求
    AbstractCommand* addmoney = new AddMoneyCommand(protocol);
    //客户端增加钻石的请求
    AbstractCommand* adddiamond = new AddDiamondCommand(protocol);
    //客户端穿装备的请求
    AbstractCommand* addequipment = new AddEquipnentCommand(protocol);
    //客户端升级的请求
    AbstractCommand* addlevel = new AddLevelCommand(protocol);
    //将客户端请求加入到队列中
    Server* server = new Server;
    server->addRequest(addmoney);
    server->addRequest(adddiamond);
    server->addRequest(addequipment);
    server->addRequest(addlevel);
    //服务器开始处理请求
    server->startHandle();
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    test();
    return a.exec();
}

5.4观察者模式
观察者模式是用于建立一种对象与对象之间的关系,一个对象发生改变时将自动通知其他对象,其他对象将相应作出反应。在观察者模式中,发生改变的对象称为观察目标,而被通知的对象称为观察者。

//抽象的英雄  抽象的观察者
class AbstractHero{
public:
    virtual void Update() = 0;
};
//具体英雄   具体观察者
class HeroA : public AbstractHero{
public:
    HeroA(){
        cout << "英雄A正在攻击BOSS" << endl;
    }
    virtual void Update(){
        cout << "英雄A停止攻击,待机状态" << endl;
    }
};
class HeroB : public AbstractHero{
public:
    HeroB(){
        cout << "英雄B正在攻击BOSS" << endl;
    }
    virtual void Update(){
        cout << "英雄B停止攻击,待机状态" << endl;
    }
};
class HeroC : public AbstractHero{
public:
    HeroC(){
        cout << "英雄C正在攻击BOSS" << endl;
    }
    virtual void Update(){
        cout << "英雄C停止攻击,待机状态" << endl;
    }
};
class HeroD : public AbstractHero{
public:
    HeroD(){
        cout << "英雄D正在攻击BOSS" << endl;
    }
    virtual void Update(){
        cout << "英雄D停止攻击,待机状态" << endl;
    }
};

//观察目标抽象
class AbstractBoss{
public:
    //添加观察者
    virtual void addHero(AbstractHero* hero) = 0;
    //删除观察者
    virtual void deleteHero(AbstractHero* hero) = 0;
    //通知观察者
    virtual void notify() = 0;
};
//具体观察者  BOSSA
class BOSSA : public AbstractBoss{
public:
    virtual void addHero(AbstractHero* hero){
        pHeroList.push_back(hero);
    }
    virtual void deleteHero(AbstractHero* hero){
        pHeroList.remove(hero);
    }
    virtual void notify(){
        for(list<AbstractHero*>::iterator it = pHeroList.begin();it != pHeroList.end(); it++){
            (*it)->Update();
        }
    }
public:
    list<AbstractHero*> pHeroList;
};

void test(){
    //创建观察者
    AbstractHero* heroA = new HeroA;
    AbstractHero* heroB = new HeroB;
    AbstractHero* heroC = new HeroC;
    AbstractHero* heroD = new HeroD;

    //创建观察目标
    AbstractBoss* bossA = new BOSSA;
    bossA->addHero(heroA);
    bossA->addHero(heroB);
    bossA->addHero(heroC);
    bossA->addHero(heroD);

    cout << "heroC阵亡。。。" << endl;
    bossA->deleteHero(heroC);

    cout << "BOSS死亡,通知其他英雄停止攻击" << endl;
    bossA->notify();
}
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    test();
    return a.exec();
}