第9章 C++常用设计模式专题

发布时间 2023-03-31 15:24:01作者: sha_ckle

单例模式

定义:确保一个类最多只有一个实例,并提供一个全局访问点

单例模式类型:

  • 懒加载

    //singleton1.h
    #ifndef SINGLETON1_H
    #define SINGLETON1_H
    
    #include<iostream>
    #include<mutex>
    
    //懒加载类型:当使用到单例对象的时候,才创建这个对象
    
    class Singleton1{
    private:
        Singleton1(){
            
        }
        
        static Singleton1 *m_instance;
        static std::mutex m_mutex;
                
    public:
        //第一个调用getInstance,new Singleton1
        //第二个调用getInstacne,
        
        //缺陷:线程不安全,多个线程调用getInstance()时,m_instacne = new Singleton1;会被多次执行。上锁
        static Singleton* getInstance(){
            if(m_inatance == nullptr){
                stf::lock_guard<std::mutex>lk(m_mutex);
                if(m_instance == nullptr){
                    m_instance = new Singleton1;
                }
            }
            return m_instance;
        }
    };
    
    Singleton1* Singleton1::m_instance = nullptr;
    std::mutex Singleton1::m_mutex
    
    #endif // SINGLETON1_H
    
    //main.cpp
    #include"singleton1.h"
    #include"singleton2.h"
    
    int main(int argc, char *argv[])
    {
        //懒加载
    	Singleton1 *s1 = new Singleton1;//调用了默认构造方法
        Singleton1 *s2 = new Singleton1;
        
        std::cout << "s1:" << s1 << std::endl;
        std::cout << "s2:" << s2 << std::endl;
        
        Singleton1 *s3 = new Singleton1::getInstance();
        Singleton1 *s4 = new Singleton1::getInstance();
        
        std::cout << "s3:" << s3 << std::endl;
        std::cout << "s4:" << s4 << std::endl;
        
        //预加载
        Singleton1 *s5 = new Singleton2::getInstance();
        Singleton1 *s6 = new Singleton2::getInstance();
        
        std::cout << "s5:" << s5 << std::endl;
        std::cout << "s6:" << s6 << std::endl;
        
        return 0;
    }
    
  • 预加载

    //singleton2.h
    #ifndef SINGLETON2_H
    #define SINGLETON2_H
    
    #include<iostream>
    
    //预加载类型:程序启动的时候,就将对象创建好
    
    class Singleton2{
    private:
        Singleton2(){
            
        }
        
        static Singleton2* m_instance;
    public:
        static Singleton2* getInstance(){
            return m_instance:
    	}
    };
    
    Singleton2* singleton2::m_instacne = new Singleton2;
    
    #endif // SINGLETON2_H
    

代理模式

//main.cpp
#include<QCoreApplication>
#include<QDebug>
/***
1.代理模式:
2.我要租房子,
3.找一个中介去租房,住的人是我。
***/
class Person{
public:
	virtual void rentHose() = 0;
};

class Milo:public Person{
public:
    void rentHouse(){
        qDebug() << "Milo需要租一件房子"
    }
};

class InterMediary:public Person{
public:
    Intermediary(Person *person):m_Person(person){
        
    }
    void rentHouse(){
        m_person->rentHouse();
        qDebug() << "中介抽取佣金20%";
    }
private:
    Person *m_person;
};

void testDelegate()
{
    Person *milo = new Milo();
    Person *intermediary = new Intermediary(milo);
    intermediary->rentHouse();
}

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

简单工厂模式

请添加图片描述

//main.cpp
#include<QCoreApplication>
#include<stdio.h>
#include<stdlib.h>
#include<iostream>

/***
什么是简单工厂模式?
简单工厂模式,是一种实例化对象的方式,只要我们输入的实例化信息(名字),就可以通过工厂方法实例化相应的实例化对象。
***/
//生产出来的手机
class TelPhone
{
public:
    enum PhoneType{Mi,Oppo,Vivo,Huawei};
    
    virtual std::string getName() = 0;
    virtual void setName(std::string name) = 0;
    virtual void setPrice(double price) = 0;
    virtual double getPrice() = 0;
        
protected:
    //手机共有的特性
    std::string name;
    double price;
};

class MiPhone:public TelPhone
{
public:
    MiPhone()
    {
        setName("mi 10");
        setPrice(5599);
    }
    std::string getName() 
    {
        return  TelPhone::name;
    }
    void setName(std::string name)
    {
        TelPhone::name = name; 
    }
    void setPrice(double price)
    {
        TelPhone::price = price;
    }
    double getPrice()
    {
        return TelPhone::price;
    }
};

class OppoPhone:public TelPhone
{
public:
    OppoPhone()
    {
        setName("Reno4");
        setPrice(2999);
    }
    std::string getName() 
    {
        return  TelPhone::name;
    }
    void setName(std::string name)
    {
        TelPhone::name = name; 
    }
    void setPrice(double price)
    {
        TelPhone::price = price;
    }
    double getPrice()
    {
        return TelPhone::price;
    }    
};

class VivoPhone:public TelPhone
{
public:
    VivoPhone()
    {
        setName("vivo x50");
        setPrice(4299);
    }
    std::string getName() 
    {
        return  TelPhone::name;
    }
    void setName(std::string name)
    {
        TelPhone::name = name; 
    }
    void setPrice(double price)
    {
        TelPhone::price = price;
    }
    double getPrice()
    {
        return TelPhone::price;
    }    
};

class HuaweiPhone:public TelPhone
{
public:
    HuaweiPhone()
    {
        setName("P40 pro");
        setPrice(6999);
    }
    std::string getName() 
    {
        return  TelPhone::name;
    }
    void setName(std::string name)
    {
        TelPhone::name = name; 
    }
    void setPrice(double price)
    {
        TelPhone::price = price;
    }
    double getPrice()
    {
        return TelPhone::price;
    }    
};

class TelPhoneFactory
{
public:
    //生产手机的方法
    //但是生产手机的时候,需要告诉工厂生产什么类型的手机
    static TelPhone* productTelPhone(TelPhone::PhontType phoneType){
        TelPhone *telp = nullptr;
        switch(phoneType)
        {
            case TelPhone:Mi:
                *telp = new MiPhone();
                break;
            case TelPhone:Oppo:
                *telp = new OppoPhone();
                break;
            case TelPhone:Vivo:
                *telp = new VivoPhone();
                break;
            case TelPhone:Huawei:
                *telp = new HuaweiPhone();
                break;
            default:
                break;
        }
    }
};

void testFactory()
{
    //需要告诉工厂生产手机,那么就要告诉工厂生产什么样的手机,通过指定参数生产怎样的手机。
    TelPhone *telp = TelPhoneFactory::productTelPhone(TelPhone::Mi);
    if(telp != nullptr)
    {
        std::cout << telp->getName() << std::endl;
        std::cout << telp->getPrince() << std::endl;
    }
}

int main(int argc, char *argv[])
{
    testFactory();
    
    return 0;
}

观察者模式

观察者模式(Observer),又叫做发布——订阅模式(Publish/Subscribe),定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。

请添加图片描述

//Sources——main.cpp
#include<QCoreApplication>
#include<stdlib.h>
#include<stdio.h>
#include<QDebug>
#include<list>
#include<iostream>

//裁判监听
class IRefereeListenner{
public:
    //开枪
    virtual void onRefereeShoot(int step) = 0;
};

class INotifier
{
public:
    virtual void registerListenner(IRefereeListenner *rl) = 0;
    virtual void removeListenner(IRefereeListenner *rl) = 0;
    virtual void notify() = 0;
};

class MoitorNotifier:public INotifier{
public:
    void registerListenner(IRefereeListenner *rl)
    {
        listenners.push_back(rl);
    }
    void removeListenner(IRefereeListenner *rl)
    {
        std::list<IRefereeListenner*>::iterator iter;
        for(iter = list.begin(); iter != listenners.end(); iter++)
        {
            if(*iter == rl)
            {
                listenners.remove(rl);
                break;
            }
        }
    }
    void notify()
    {
        std::list<IRefereeListenner*>::iterator iter;
        for(iter = list.begin(); iter != listenners.end(); iter++)
        {
            //裁判开枪了
        	(*iter)->onRefereeShoot();
        }
    }
    void setStep(int step)
    {
        m_step = step;
        notify();
    }
private:
    std::list<IRefereListeener*>listenners;
    int m_step;
};

class Mark:public IRefereeListenner{
public:
    void onRefereeShoot(int step)
    {
        startRunning(step);
    }
    void startRunning(int step)
    {
        qDebug() << "Mark 开始跑";
    }
};

class King:public IRefereeListenner{
public:
    void onRefereeShoot(int step)
    {
        startRunning(step);
    }
    void startRunning(int step)
    {
        qDebug() << "King 开始跑";
    }
};

class Darren:public IRefereeListenner{
public:
    void onRefereeShoot(int step)
    {
        startRunning(step);
    }
    void startRunning(int step)
    {
        qDebug() << "Darren 开始跑";
    }
};

class Vico:public IRefereeListenner{
public:
    void onRefereeShoot(int step)
    {
        startRunning(step);
    }
    void startRunning(int step)
    {
        qDebug() << "Vico 开始跑";
    }
};

void testObserver()
{
    MoitorNotifier monitor;
    
    Mark mark;
    King king;
    Darren darren;
    Vico vico;
    
    monitor.registerListenner(&mark);
    monitor.registerListenner(&king);
    monitor.registerListenner(&darren);
    monitor.registerListenner(&vico);
    
    //
    qDebug() << "开始跑";
    monitor.setStep(1);
    
    //将mark移除比赛,其余人继续跑
    moitor.removeListeener(&mark);
    monitor.setStep(2);
}

int main(int argc, char *argv[])
{
    testObserver();
    
    return 0;
}

原型模式

定义:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个原型相同或相似的新对象。

请添加图片描述

//prototype->main.cpp
#include<iostream>

class Prototype{
public:
    Prototype(){
        
    }
    virtual ~Prototype(){
        
    }
    virtual Prototype Clone() = 0;
};

class ConcretePrototype:public Prototype{
public:
    ConcretePrototype():m_counter(0){
        
    } 
    virtual ~ConcreteProtorype(){
        
    }
    
    //拷贝构造函数
    ConcretePrototype(const ConcretePrototype& cp){
        m_counter = cp.m_counter
    }
    
    //复制自身
    virtual ConcretePrototype* Clone(){
        return new ConcretePrototype(*this);
    }
    
    int getcounter(){
        return m_counter
    }
    
private:
    int m_counter;
}

int main()
{
    //生成对象
    ConcretePrototype* cpA = new ConcretePrototype();
    //复制自身
    ConcretePrototype* cpB = (ConcretePrototype*)cpA->Clone();
    
    printf("cpA m_counter=%d",cpA->getCounter());
    delete cpA;
    cpA = NULL;
    printf("cpA对象删除\n");
    
    printf("cpB m_counter=%d",cpB->getCounter());
    delete cpB;
    cpB = NULL;
    printf("cpB对象删除\n");
    
    return 0;
}

策略模式

定义:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。该模式使得算法可独立于使用它的客户而变化。

请添加图片描述

//steategy->main
#include<iostream>
using namespace std;

enum StrategyType{
    Strategy_Night;
    Strategy_Weekend;
    Strategy_Holiday;
}

//策略类
class Strategy{
public:
    //加班算法
    virtual void algorithm() = 0;
    
    virtual ~Strategy(){
        
    }
};

//晚上加班算法
class StrategyNight:public Strategy{
public:
    //加班算法
    void algorithm(){
        cout << "晚上加班计算方法" << endl;
    }
    
    virtual ~Strategy(){
        
    }
};

//周末加班算法
class StrategyWeekend:public Strategy{
public:
    //加班算法
    void algorithm(){
        cout << "周末加班计算方法" << endl;
    }
    
    virtual ~Strategy(){
        
    }
};

//节假日加班算法
class StrategyHoliday:public Strategy{
public:
    //加班算法
    void algorithm(){
        cout << "节假日加班计算方法" << endl;
    }
    
    virtual ~Strategy(){
        
    }
};

class Context
{
public:
    Context(StrategyType strategyType){
        switch(strategyType)
        {
            case Strategy_Night:
                pStrategy = new StrategyNight();
                break;
            case Strategy_Weekend:
                pStrategy = new StrategyWeekend();
                break;
            case Strategy_Holiday:
                pStrategy = new StrategyHoliday();
                break;
        }
    }
    //加班工资
    void overtimePay()
    {
        if(pStrategu){
            pStrategy->algorithm();
        }
    }
    ~Context(){
        if(pStrategy)
        {
            delete pStratrgy;
        }
    }
    
private:
    Strategy* pStrategy;
}

int main()
{
    Context* pContext = new Context(Strategy_Night);
    pContext->overtimePay();
    if(pContext){
        delete pContext;
    }
    
    return 0;
}

中介者模式

定义:一个中介对象来封装一系类对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。

请添加图片描述

//mediator->main.cpp
#include<iostream>
#include<string>
#include<vector>


//雇员
class Employee{
private:
    string m_strName;
    string m_strContent;
    
public:
    Employee(string strName):m_strName(strName){
        
    }
    void setName(string strName){
        m_strName = strName;
    }
    string getName(){
        return m_strName;
    }
    void setContent(string strContent){
        m_strContent = strContent;
    }
    string getContent(){
        if(m_strContent.empty()){
            return "收到";
        }
        return m_strContent;
    }
    
    //说话
    virtual void talk() = 0;
};

//老板
class Boss:public Employee{
public:
    Boss(string str):Employee(str){}
    
    void talk(){
        cout << getName() << "说:" << getContent() << endl;
    }
};

//经理
class Manager:public Employee{
public:
    Manager(string str):Employee(str){}
    
    void talk(){
        cout << getName() << "说:" << getContent() << endl;
    }
};

//保安
class Securtity:public Employee{
public:
    Securtity(string str):Employee(str){}
    
    void talk(){
        cout << getName() << "说:" << getContent() << endl;
    }
};

//中介类
class Mediator{
protected:
    vector<Employee*>vec_emp;
    
public:
    void addEmployee(Employee* emp){
        vec_emp.push_back(emp);
    }
    
    virtual void notify(Employee* emp) = 0;
};

//假期中介类
class HolidaysMediator{
public:
    void notify(Employee* emp){
        //传过来的对象说话
        emp->talk();
        
        for(int i = 0; i < vec_emp.size(); i++)
        {
            if(emp != vec_emp[i])
            {
                //其他对象说话
                vec_emp[i]->talk();
            }
        }
    }
    
    virtual void notify(Employee* emp) = 0;
};

int main()
{
    //假期中介对象
    HolidaysMediator holidaysMediator;
    Boss* boss = new Boss("老板");
    Manager* manager = new Manager("老板");
    Securtity* securtity = new Securtity("老板");
    
    holidayMediator.addEmployee(boss);
    holidayMediator.addEmployee(manager);
    holidayMediator.addEmployee(securtity);
    
    boss->setContent("明天放假");
    
    holidaysMediator.notify(boss);
    
    return 0;
}

责任链模式

责任链,顾名思义,就是用来处理相关事务责任的一条执行链,执行链上有多个节点,每个结点都有机会(条件匹配)处理请求事务,如果某个结点处理完了就可以根据实际业务需求传递给下一个结点继续处理或者返回处理完毕。

请添加图片描述

日志输出:

ERROR、WARN、INFO、DEBUG

ERROR > WARN > INFO > DEBUG

//Chain->main.cpp
#include<iostream>
#include<string>

class Logger{
public:
    enum LEVEL{
        DEBUG = 1,
        INFO,
        WARN,
        ERROR,
    };
    
    LEVEL level = LEVEL::DEBUG;
    
    logger(){
        
    }
    
    virtual ~Logger(){
        
    }
    
    void logMessage(LEVEL level, std::string message){
        if(m_level <= level)
        {
            write(message);
        }
        
        if(m_nextLogger != NULL){
            m_nextLogger->logMessage(level, message);
        }
    }
    
    void setNextLogger(Logger* nextLogger){
        m_nextLogger = nextLogger;
    }
protected:
    virtual void write(std::string logger){
        
    };
    Logger* m_nextLogger;
};

class DebugLogger:public Logger{
public:
    DebugLogger(LEVEL level){
        m_level = level;
    }
    
    void write(std::string logger){
        std::cout << "Debug Logger:" << m_level << ",message:" << logger << std::endl;
    }
};

class InfoLogger:public Logger{
public:
    InfoLogger(LEVEL level){
        m_level = level;
    }
    
    void write(std::string logger){
        std::cout << "Debug Logger:" << m_level << ",message:" << logger << std::endl;
    }
};

class WarnLogger:public Logger{
public:
    WarnLogger(LEVEL level){
        m_level = level;
    }
    
    void write(std::string logger){
        std::cout << "Debug Logger:" << m_level << ",message:" << logger << std::endl;
    }
};

class ErrorLogger:public Logger{
public:
    ErrorLogger(LEVEL level){
        m_level = level;
    }
    
    void write(std::string logger){
        std::cout << "Debug Logger:" << m_level << ",message:" << logger << std::endl;
    }
};

class Client{
public:
    Client(){}
    ~Client(){}
    
    void test(){
        Logger* logger = getChainOfLoggers();
        logger->logMessage(Logger::DEBUG, "这是DEBUG信息");
        logger->logMessage(Logger::INFO, "这是INFO信息");
        logger->logMessage(Logger::WARN, "这是WARN信息");
        logger->logMessage(Logger::ERROR, "这是ERROR信息");
    }
private:
    Logger* getChainOfLoggers(){
        Logger *debug = new DebugLogger(Logger::DEBUG);
        Logger *info = new InfoLogger(Logger::INFO);
        Logger *warn = new WarnLogger(Logger::WARN);
        Logger *error = new ErrorLogger(Logger::ERROR);
        
        error->setNextLogger(warn);
        warn->setNextLogger(info);
        info->setNextLogger(debug);
        
        return error;
    }
};

int main()
{
    Client client;
    client.test();
    
    return 0;
}