总结一些平时用得比较多的设计模式

代理模式

是一种结构型模式

代理模式 Proxy 模式

客户(实际对象) -> 助理Proxy(代理类) ->老板(委托类)

即委托类通过代理类来控制实际对象的访问权限

#include<iostream>
#include<memory>

using namespace std;

//基类
class Video{
public:
    virtual void showCommon() = 0;
    virtual void showVIP() = 0;
    virtual void showTicket() = 0;
};

//委托类
class CoshVideo : public Video{
public:
    virtual void showCommon(){
        cout<<"Cosh : Common"<<endl;
    };

    virtual void showVIP(){
        cout<<"Cosh : VIP"<<endl;
    };

    virtual void showTicket(){
        cout<<"Cosh : Ticket"<<endl;
    };
};


//代理类1
class CommonUser : public Video{
public:
    CommonUser(){base = new CoshVideo();}
    ~CommonUser(){delete base;}
    virtual void showCommon(){
        base->showCommon();
    };

    virtual void showVIP(){
        cout<<"Common : VIP Banned"<<endl;
    };

    virtual void showTicket(){
        cout<<"Common : Ticket Banned"<<endl;
    };
private:
    Video* base;
};

//代理类2
class VIPUser : public Video{
public:
    VIPUser(){base = new CoshVideo();}
    ~VIPUser(){delete base;}
    virtual void showCommon(){
        base->showCommon();
    };

    virtual void showVIP(){
        base->showVIP();
    };

    virtual void showTicket(){
        cout<<"VIP : Ticket Banned"<<endl;
    };
private:
    Video* base;
};

//代理类3
class TicketUser : public Video{
public:
    TicketUser(){base = new CoshVideo();}
    ~TicketUser(){delete base;}
    virtual void showCommon(){
        base->showCommon();
    };

    virtual void showVIP(){
        base->showVIP();
    };

    virtual void showTicket(){
        base->showTicket();
    };
private:
    Video* base;
};



void show(std::unique_ptr<Video> &p){
    p->showCommon();
    p->showVIP();
    p->showTicket();
    cout<<endl;
}

signed main(){
    // unique_ptr<Video> user(new CommonUser());
    std::unique_ptr<Video> common(new CommonUser());
    std::unique_ptr<Video> VIP(new VIPUser());
    std::unique_ptr<Video> ticket(new TicketUser());
    show(common);
    show(VIP);
    show(ticket);
    return 0;
}

单例模式

一个类不管创建多少次对象,永远只能得到该类型的一个对象的实例

使用情景:日志模块,数据库模式

饿汉式单例模式:还没有获取实例对象,实例对象就已经产生了(一定是线程安全的)

懒汉式单例模式:唯一的实例对象,第一次 获取它时才产生(会有线程安全问题,可避免)

一般情况下,由于单例模式的初始化会有大量读取文件IO,或者加载配置的代码

所以懒汉式单例模式更受到青睐

使用单例模式时,记得delete掉拷贝函数和赋值运算符重载

饿汉式单例模式:

class Singleton{
public:
    static Singleton* getSingleton(){          //#3  后去类的唯一实例对象的接口方法
        return &instance;
    }
    static void get(){
        std::cout<<id<<std::endl;
    }
private:
    static Singleton* instance;      //#2 定义一个唯一的类的实例对象
    static const int id = 10;
    Singleton(){        //#1 构造函数私有化
    }
    Singleton& operator= (const Singleton& a) = delete;
    Singleton(const Singleton& a) = delete;
};
Singleton Singleton::instance;	//在编译的时候已经构造出了对象

signed main(){
    Singleton* s1 = Singleton::getSingleton();
    Singleton* s2 = Singleton::getSingleton();
    Singleton* s3 = Singleton::getSingleton();
    s1->get();
    s2->get();
    s3->get();
}

懒汉式单例模式

//利用互斥锁构造函数对象
mutex mtx;
class Singleton{
public:
    static Singleton* getSingleton(){          //#3  后去类的唯一实例对象的接口方法
        if(instance == nullptr){
            lock_guard<std::mutex> lck(mtx);
            if(instance == nullptr){
                Singleton();
            }
        }
        return instance;
    }
private:
    static Singleton* instance;      //#2 定义一个唯一的类的实例对象
    static const int id = 10;
    Singleton(){        //#1 构造函数私有化
    }
    Singleton& operator= (const Singleton& a) = delete;
    Singleton(const Singleton& a) = delete;
};

在该情况下记得使用双重判定,否则仍可能导致线程安全问题

//利用编译static时,编译器会自动对static静态成员上锁的特性构造
#include<iostream>
#include<mutex>
#include<thread>
using namespace std;

mutex mtx;
class Singleton{
public:
    static Singleton* getSingleton(){          //#3  后去类的唯一实例对象的接口方法
        //  函数静态局部,在函数第一次访问静态资源时才会被使用
        static Singleton instance;     //#2 定义一个唯一的类的实例对象
        return &instance;
    }
private:
    static const int id = 10;
    Singleton(){        //#1 构造函数私有化
    }
    Singleton& operator= (const Singleton& a) = delete;
    Singleton(const Singleton& a) = delete;
};

signed main(){
    Singleton* s1 = Singleton::getSingleton();
    Singleton* s2 = Singleton::getSingleton();
}

观察者模式

是一种行为型模式

行为型模式:主要关注的是对象之间的通信

观察者-监听者模式(发布-订阅模式)设计模式:主要是关注的是对象的一对多的关系,也就是多个对象都依赖一个对象,当该对象的状态发生改变的时候,其他对象都能够接收到相对应的通知

一组数据(数据对象) ->通过这一组数据 ->曲线图(对象1)/柱状图(对象2)/圆饼图(对象3)

当数据对象改变时,对象1,对象2,对象3应该及时地收到相对应的通知并改变自身状态

Observe1 Observer2 Observe3

​ subject(主题) , 当主题有更改时,应该及时通知相应的观察者,去处理相应的事件

#include<iostream>
#include<memory>
#include<unordered_map>
#include<list>


using namespace std;

//观察者抽象类
class Observer 
{
public:
    // 处理消息的接口
    virtual void handleMessage(int msgid) = 0;
    
};


class Observer1 : public Observer
{
public:
    Observer1(int id):id(id){}
    // 处理消息的接口
    virtual void handleMessage(int msgid){
        switch (msgid)
        {
        case 1:
            cout<<id<<": call back Message1"<<endl;
            break;
        case 2:
            cout<<id<<": call back Message2"<<endl;
            break;
        default:
            break;
        }
    }
private:
    int id;
};


class Observer2 : public Observer
{
public:
    Observer2(int id):id(id){}
    // 处理消息的接口
    virtual void handleMessage(int msgid){
        switch (msgid)
        {
        case 1:
            cout<<id<<": call back Message1"<<endl;
            break;
        case 3:
            cout<<id<<": call back Message3"<<endl;
            break;
        default:
            break;
        }
    }
private:
    int id;
};


class Observer3 : public Observer
{
public:
    Observer3(int id):id(id){}
    // 处理消息的接口
    virtual void handleMessage(int msgid){
        switch (msgid)
        {
        case 2:
            cout<<id<<": call back Message2"<<endl;
            break;
        case 3:
            cout<<id<<": call back Message3"<<endl;
            break;
        default:
            break;
        }
    }
private:
    int id;
};

class Subject{
public:
    void addObserver(Observer* observer ,int msgid){
        m[msgid].push_back(observer);
    }

    void dispatch(int msgid){
        for(auto it : m[msgid])
        {
          	it->handleMessage(msgid);
    	}
    }
private:
    unordered_map<int , list<Observer*>> m;
};



signed main(){
    Subject sub1;
    Observer *ob1 = new Observer1(1);
    Observer *ob2 = new Observer2(2);
    Observer *ob3 = new Observer3(3);
    sub1.addObserver(ob1 , 1);
    sub1.addObserver(ob1 , 2);
    sub1.addObserver(ob2 , 1);
    sub1.addObserver(ob2 , 3);
    sub1.addObserver(ob3 , 2);
    sub1.addObserver(ob3 , 3);

    for(;;){
        int a;
        cout<<"enter : ";
        cin>>a;
        if(a == -1) break;
        sub1.dispatch(a);
    }

    delete ob1;
    delete ob2;
    delete ob3;
    return 0;
}

工厂模式

简单工厂 :Simple Factory

工厂方法 : Factory Method

抽象工厂: Abstract Factory

工厂模式:主要是封装了对象的创建

简单工厂

把对象的创建封装在一个接口函数里面,通过传入不同的标识,返回创建的对象

客户不用负责new对象,不用了解对象创建的详细过程

提供创建对象实例的接口函数不闭合,不能对修改关闭

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

class Car
{
public:
    Car(string name):_name(name){}
    virtual void show() = 0;
protected:
    string _name;
};

class Bmw : public Car
{
public:
    Bmw(string name) :Car(name){}
    void show(){
        cout<<"Got a new BWM"<<endl;
    }
};

class Audi : public Car
{
public:
    Audi(string name) :Car(name){}
    void show(){
        cout<<"Got a new Audi"<<endl;
    }
};

enum CarType{
    BMW , AUDI
};

//
class simpleFactory{
public:
    //不满足开闭原则,逻辑会出现问题
    Car* createCar(CarType ct){
        switch (ct)
        {
        case BMW:
            return new Bmw("X1");
            break;
        case AUDI:
            return new Audi("A6");
            break;
        default:
            cerr<<"post error"<<endl;
            break;
        }
    }
};

signed main(){
    unique_ptr<simpleFactory> factory(new simpleFactory()) ;
    unique_ptr<Car> p1(factory->createCar(BMW));
    unique_ptr<Car> p2(factory->createCar(AUDI));
    p1->show() , p2->show();

    return 0;
}

工厂方法

定义了一个Factory积累,提供了一个纯虚函数(创产品),定义派生类(具体产品的工厂)负责对应的产品,可以做到不同的产品,在不用的工厂里面创建,能够对现有工厂,以及产品的修改的关闭

实际上,很多产品是有关联关系的,属于一个产品簇,不应该放在不同的工厂里面去创建

一是:不符合实际的产品对象创建逻辑

二是:工厂类太多了,不好维护

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

class Car
{
public:
    Car(string name):_name(name){}
    virtual void show() = 0;
protected:
    string _name;
};

class Bmw : public Car
{
public:
    Bmw(string name) :Car(name){}
    void show(){
        cout<<"Got a new BWM"<<endl;
    }
};

class Audi : public Car
{
public:
    Audi(string name) :Car(name){}
    void show(){
        cout<<"Got a new Audi"<<endl;
    }
};

enum CarType{
    BMW , AUDI
};


//创建一个大工厂,为其他工厂提供同一的抽象方法
class Factory{
public:
    virtual Car* createCar(string name) = 0;
};

class BWMFactory  : public Factory{
public:
    virtual Car* createCar(string name){
        return new Bmw(name);
    }
};

class AudiFactory : public Factory{
public:
    virtual Car* createCar(string name){
        return new Audi(name);
    }
};

signed main(){
    unique_ptr<Factory> BwmFactory(new BWMFactory()) ;
    unique_ptr<Car> car1(BwmFactory->createCar("X3"));
    
    unique_ptr<Factory> audiFactory(new AudiFactory()) ;
    unique_ptr<Car> car2(audiFactory->createCar("R6"));

    car1->show() , car2->show();
    return 0;
}

抽象工厂

把有关联关系的,属于一个产品簇的所有产品常见的接口函数,放在一个抽象工厂里面

派生类(具体产品的工厂)应该负责创建产品簇里面的所有产品

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

//假设宝马公司还生产灯,那么应该把灯放在宝马公司的工厂内生产
//不用额外创建新的灯工厂(避免额外的派生类过多不好维护)
class Light{
public:
    Light(string name):_name(name){}
    void show() {cout<<"this is a light call :" << _name<<endl;}
private:
    string _name;
};

class BwmLight : public Light{
public:
    BwmLight(string name) :Light(name){};
};

class Car
{
public:
    Car(string name):_name(name){}
    virtual void show() = 0;
protected:
    string _name;
};

class Bmw : public Car
{
public:
    Bmw(string name) :Car(name){}
    void show(){
        cout<<"Got a new BWM"<<endl;
    }
};

class Audi : public Car
{
public:
    Audi(string name) :Car(name){}
    void show(){
        cout<<"Got a new Audi"<<endl;
    }
};

enum CarType{
    BMW , AUDI
};

//
class Factory{
public:
    virtual Car* createCar(string name) = 0;
    virtual Light* createLight(string name) = 0;
};

class BWMFactory  : public Factory{
public:
    virtual Car* createCar(string name){
        return new Bmw(name);
    }
    virtual Light* createLight(string name){
        return new BwmLight(name);
    }
};

class AudiFactory : public Factory{
public:
    virtual Car* createCar(string name){
        return new Audi(name);
    }
    virtual Light* createLight(string name){};
};

signed main(){
    unique_ptr<Factory> BwmFactory(new BWMFactory()) ;
    unique_ptr<Car> car1(BwmFactory->createCar("X3"));
    unique_ptr<Light> light1(BwmFactory->createLight("ll"));

    unique_ptr<Factory> audiFactory(new AudiFactory()) ;
    unique_ptr<Car> car2(audiFactory->createCar("R6"));

    car1->show() , car2->show() , light1->show();
    return 0;
}

适配器模式

适配器模式:让不兼容的接口一起工作

电脑 ->投影(VGA,HDMI,Type-C)等 ->投影仪

VGA接口的电脑 == VGA投影仪(就不需要接口转换)

#include<iostream>
#include<memory>

using namespace std;

//VGA接口类
class VGA
{
    public:
        virtual void play() = 0;
};


//HDMI接口类
class HDMI
{
    public:
        virtual void play() = 0;
};

//支持VGA接口的投影仪
class TV01 : public VGA
{
    public:
        virtual void play() {
            cout<<"Play By VGA";
        }
};


//支持HDMI接口的投影仪
class TV02 : public HDMI
{
    public:
        virtual void play() {
            cout<<"Play By HDMI";
        }
};


// 方法一:换电脑(即进行代码重构)
// 方法二: 买一个转换头,能够把VGA信号转换成HDMI信号(适配器方法)
class Computer1
{
public:
    // 由于电脑只支持VGA接口,所以偶该方法的参数也只能支持VGA接口的指针/引用
    void playVideo(VGA *pVGA){
        pVGA ->play();
    }
};

//由于电脑(VGA接口)与投影仪(HDMI接口)不兼容,所以需要添加适配器类
class VGAToHDMIAdapter: public VGA
{
public:
    VGAToHDMIAdapter(HDMI *p) : pHdmi(p){}
    void play(){
        pHdmi->play();
    }

private:
    HDMI* pHdmi;
};

signed main(){
    unique_ptr<Computer1> com(new Computer1);
    com->playVideo(new VGAToHDMIAdapter(new TV02));
}

装饰器模式

Decorator 装饰器模式

属于一个结构性模式

与代理模式非常相似

通过子类实现的方式来完成功能增强的问题,为了增强现有类的功能,通过实现子类的方式

文章作者: cosh
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 cosh'blog
Others
喜欢就支持一下吧