常见的设计模式学习

本文详细介绍了C++中的几种设计模式,包括单例模式(懒汉和饿汉实现)、工厂模式(简单工厂、工厂方法、抽象工厂)、代理模式、装饰器模式以及适配器模式。这些模式主要用于控制对象的创建和管理,以及对象间的通信和接口兼容性问题。此外,还展示了观察者模式如何实现对象间的发布-订阅通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我的理解是:

  1. 单例模式和工厂模式都是在对 对象的构造 上下功夫。
  2. 代理模式、装饰器模式、适配器模式 都是对原有类的重构,通过继承公共基类,并添加对应类的成员变量。
  3. 观察者模式(行为型模式),主要关注的是对象之间的通信。

1. 单例模式(懒汉和饿汉)

一个类不管创建多少次对象,用于只会得到该类型一个对象的示例,比如:日志模块;数据库模块;

class Singleton
{
public : 
    static Singleton &getInstance() 
    {
        static Singleton instance ; 
        return instance ; 
    }
private : 
    Singleton() {} ; # 构造函数私有化
    ~Singleton() {} ; 
    Singleton (const Singleton&) = delete ; 
    Singleton & operator = (const Singleton &) = delete ;
}

2. 工厂模式(简单工厂、工厂方法、抽象工厂):

将对象具体的实例化细节封装起来

  • 简单工厂:把对象的创建封装在一个接口函数里面,通过传入不同的标识,返回创建的对象。 但是不符合软件设计的 [ 开-闭 ] 原则 ,也就是说需要频繁的在 SimpleFactory 中进行修改
class Car
{
public  :
    Car(const string &name) : _name(name) {}
    virtual void show() = 0 ; 
protected : 
    string _name ; 
} ; 

class BMW : public Car
{
public : 
    BMW(const string &name) : Car(name) {}
    void show()
    {
        cout << "获取一辆宝马汽车" << endl ; 
    }
} ; 

class AUDI : public Car
{
public : 
    AUDI(const string &name) : Car(name) {}
    void show()
    {
        cout << "获取一辆奥迪汽车" << endl ; 
    }
} ; 


// 简单工厂
enum CarType{ bmw , audi } ; 

class SimpleFactory
{
public  :
    Car* createCar(CarType ct) 
    {
        switch (ct)
        {
        case bmw :
            return new BMW("X1") ; 
        case audi :
            return new AUDI("A6") ; 
        default:
            cerr << "传入工厂的参数不正确: " << ct << endl ;
            break;
        }  
    }
} ; 
int main()
{
    // 这是已往的做法,C++ 多态
    // Car *p1 = new BMW("X1")  ; 
    // Car *p2 = new AUDI("A6") ; 
	// 简单工厂
    SimpleFactory *factory = new SimpleFactory() ; 
    Car *p1 = factory->createCar(bmw) ; 
    Car *p2 = factory->createCar(audi) ; 
    p1->show() ; 
    p2->show() ; 

    delete p1 ; 
    delete p2 ; 
    delete factory ; 

    return 0 ; 
} 
  • 工厂方法:提供了一个纯虚函数(创建产品),定义派生类(具体产品的工厂)负责创建对应的产品;但是很多产品是有关联关系的,属于一个产品簇,不应该放在不同的工厂里创建,会导致工程类增多不好维护;另外也不符合实际逻辑
// 工厂方法
class Factory
{
public : 
    virtual Car* createCar(const string& name) = 0 ; 
};
// 宝马工厂
class BMWFactory : public Factory
{
public : 
    Car* createCar(const string& name) 
    {
        return new BMW(name) ;   
    }
} ; 

// 奥迪工厂
class AUDIFactory : public Factory
{
public : 
    Car* createCar(const string& name) 
    {
        return new AUDI(name) ;   
    }
} ; 

int main()
{
    unique_ptr<Factory> bmwfactory(new BMWFactory()) ; 
    unique_ptr<Factory> audifactory(new AUDIFactory()) ; 
    unique_ptr<Car> p1(bmwfactory->createCar("X6")) ; 
    unique_ptr<Car> p2(audifactory->createCar("A8")) ; 

    p1->show() ; 
    p2->show() ; 

    return 0 ; 
}
  • 抽象工厂:把一个产品簇的所有产品创建的接口函数,放在一个抽象工厂里面,派生类负责创建该产品簇里面的所有产品。
// 系列产品 1
class Car
{
public  :
    Car(const string &name) : _name(name) {}
    virtual void show() = 0 ; 
protected : 
    string _name ; 
} ; 

class BMW : public Car
{
public : 
    BMW(const string &name) : Car(name) {}
    void show()
    {
        cout << "获取一辆宝马汽车" << endl ; 
    }
} ; 

class AUDI : public Car
{
public : 
    AUDI(const string &name) : Car(name) {}
    void show()
    {
        cout << "获取一辆奥迪汽车" << endl ; 
    }
} ; 


// 系列产品 2
class Light
{
public : 
    virtual void show() = 0 ; 
} ; 

class BMWLight : public Light
{
public : 
    void show() { cout << "BMW light" << endl ; }
};

class AUDILight : public Light
{
public : 
    void show() { cout << "AUDI light" << endl ; }
} ;

// 工厂方法 => 抽象工厂 (对有一组关联关系的产品簇,提供产品对象的统一创建)
class AbstractFactory
{
public : 
    virtual Car* createCar(const string& name) = 0 ; // 工厂方法 , 创建汽车
    virtual Light* createLight() = 0 ;               // 工厂方法 , 创建汽车关联的产品,车灯
};

// 宝马工厂
class BMWFactory : public AbstractFactory
{
public : 
    Car* createCar(const string& name) 
    {
        return new BMW(name) ;   
    }
    Light *createLight()
    {
        return new BMWLight() ; 
    }
} ; 

// 奥迪工厂
class AUDIFactory : public AbstractFactory
{
public : 
    Car* createCar(const string& name) 
    {
        return new AUDI(name) ;   
    }
    Light *createLight()
    {
        return new AUDILight() ; 
    }
} ; 

int main()
{
    unique_ptr<AbstractFactory> bmwfactory(new BMWFactory()) ; 
    unique_ptr<AbstractFactory> audifactory(new AUDIFactory()) ; 
    unique_ptr<Car> p1(bmwfactory->createCar("X6")) ; 
    unique_ptr<Car> p2(audifactory->createCar("A8")) ; 

    unique_ptr<Light> l1(bmwfactory->createLight()) ; 
    unique_ptr<Light> l2(audifactory->createLight()) ; 
    p1->show() ; 
    p2->show() ; 
    l1->show() ; 
    l2->show() ; 
    return 0 ; 
}

3. 代理 Proxy 模式

通过代理类控制实际对象的访问权限 (类的组合关系) ; 代理类和委托类都是继承于 VideoSite

class VideoSite
{
public : 
    virtual void freeMovie()   = 0 ; 
    virtual void vipMovie()    = 0 ; 
    virtual void ticketMovie() = 0 ; 
} ; 

// 委托类
class FixBugVideoSite : public VideoSite
{
public : 
    virtual void freeMovie() 
    {
        cout << "观看免费电影" << endl ;
    }
    virtual void vipMovie() 
    {
        cout << "观看 VIP 电影" << endl ;
    }
    virtual void ticketMovie() 
    {
        cout << "用券观看电影"  << endl ; 
    }
} ; 

// 代理类 代理 FixBugVideoSite
class FreeVideoSiteProxy : public VideoSite
{
public : 
    FreeVideoSiteProxy() { pVideo = new FixBugVideoSite() ; }
    ~FreeVideoSiteProxy() { delete pVideo ; }

    virtual void freeMovie() 
    {
        pVideo->freeMovie() ; // 通过代理对象的 freeMovie ,来访问真正委托类的 freeMovie() ; 
    }

    virtual void vipMovie() 
    {
        cout << "您目前只是普通游客, 需要升级成 VIP , 才能观看 VIP 电影" << endl ;
    }
    virtual void ticketMovie() 
    {
        cout << "您目前没有券, 需要购买电影券,才可以观看电影" << endl ; 
    }

private : 
    VideoSite *pVideo ; 
} ; 

// 代理类 代理 FixBugVideoSite
class VipVideoSiteProxy : public VideoSite
{
public : 
    VipVideoSiteProxy() { pVideo = new FixBugVideoSite() ; }
    ~VipVideoSiteProxy() { delete pVideo ; }

    virtual void freeMovie() 
    {
        pVideo->freeMovie() ; // 通过代理对象的 freeMovie ,来访问真正委托类的 freeMovie() ; 
    }

    virtual void vipMovie() 
    {
        pVideo->vipMovie() ;
    }
    virtual void ticketMovie() 
    {
        cout << "您目前没有券, 需要购买电影券,才可以观看电影" << endl ; 
    }

private : 
    VideoSite *pVideo ; // 类之间进行组合: FixBugVideoSite 已经完成了全部的功能
} ; 

void watchMovice(unique_ptr<VideoSite> &ptr)
{
    ptr->freeMovie() ;
    ptr->vipMovie() ;
    ptr->ticketMovie() ; 
}
int main()
{
    unique_ptr<VideoSite> p1(new FreeVideoSiteProxy()) ;  // 用户智能访问代理对象
    unique_ptr<VideoSite> p2(new VipVideoSiteProxy()) ;  
    watchMovice(p1) ; 
    watchMovice(p2) ; 

    return 0 ; 
}

4. 装饰器模式:主要是增加现有类的功能

[外链图片转存中...(img-6THsDN87-1684395747379)]

// 装饰器模式
class Car
{
public : 
    virtual void show() = 0 ; 
} ; 

class BMW : public Car
{
public : 
    void show () 
    {
        cout << "这是辆宝马汽车,配置有:基类" << endl ; 
    }
} ; 

class AUDI : public Car
{
public : 
    void show () 
    {
        cout << "这是辆奥迪汽车,配置有:基类" << endl ; 
    }
} ; 

// 装饰器1 定速巡航 都是通过继承父类 Car ,并且构造函数需要定义成员变量接受上传过来的 类对象
class ConcreteDecorator01 : public Car 
{
public : 
    ConcreteDecorator01(Car *p) : pCar(p) {}
    void show() 
    {
        pCar->show() ; 
        cout << ", 定速巡航" << endl ;
    }
private : 
    Car *pCar ; 
} ; 

// 装饰器2 自动刹车
class ConcreteDecorator02 : public Car 
{
public : 
    ConcreteDecorator02(Car *p) : pCar(p) {}
    void show() 
    {
        pCar->show() ; 
        cout << ", 自动刹车" << endl ; // 调用对应的函数
    }
private : 
    Car *pCar ; 
} ; 

int main()
{
    unique_ptr<Car> p1 (new ConcreteDecorator01(new BMW())) ; 
    unique_ptr<Car> p2 (new ConcreteDecorator02(new AUDI())) ; 
    unique_ptr<Car> p3 (new ConcreteDecorator02(p1.get())) ; 
    p1->show() ; 
    p2->show() ; 
    p3->show() ; 

    return 0 ; 
}

5. 适配器模式:让不兼容的接口可以在一起工作

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

// TV01 表示支持 VGA 接口的投影仪
class TV01 : public VGA
{
public : 
    void play() 
    {
        std::cout << "通过 VGA 接口连接投影仪 , 进行视频播放" << endl ;
    }
} ; 

// 进了一批新的投影仪,但是新的投影仪只支持 HDMI 接口
class HDMI
{
public : 
    virtual void play() = 0 ; 
} ; 

class TV02 : public HDMI
{
public : 
    void play() 
    {
        std::cout << "通过 HDMI 接口连接投影仪 , 进行视频播放" << endl ;
    }
} ; 

// 实现一个电脑类(只支持 VGA 接口)
class Computer
{
public : 
    // 由于电脑只支持 VGA 接口,所以该方法的参数也只能支持 VGA 接口的指针/引用
    void playVideo(VGA *pVGA) 
    {
        pVGA->play() ; 
    }
} ; 

/*
方法1 : 换一个支持 HDMI 接口的电脑,代码重构
方法2 : 买一个转换头,将 VGA 信号转化成 HDMI 信号, 添加适配器类
*/

class VGAToHDMIAdapter : public VGA  
{
public : 
    VGAToHDMIAdapter(HDMI *p) : pHDMI(p) {}
    void play() // 该方法就相当于转换头,做不同接口的信号转换
    {
        pHDMI->play() ; 
    }
private:
    HDMI *pHDMI ; 
};

int main()
{
    Computer computer ; 
    computer.playVideo(new TV01()) ; 
    // 直接传入 TV02 是不行的,因为 computer 只支持 VGA 接口
    // computer.playVideo(new TV02()) ; 
    // 故添加一个适配器类,重写对应的方法
    computer.playVideo(new VGAToHDMIAdapter(new TV02()) ) ; 
    return 0 ; 
}

6. 观察者模式(发布-订阅模式):

行为型模式,主要关注的是对象之间的通信。当一个对象的状态发生改变时,其他对象都会接收到相应的通知。
在这里插入图片描述

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

// 第一个观察者实例
class Obsever1 : public Observer
{
public :
    void handle(int msgid) 
    {
        switch (msgid)
        {
        case 1:
            cout << "Observer1 recv 1 msg " << endl ;
            break;
        case 2:
            cout << "Observer1 recv 2 msg " << endl ;
            break;
        case 3:
            cout << "Observer1 recv 3 msg " << endl ;
            break;
        default:
            break;
        }
    }
};

// 第二个观察者实例
class Obsever2 : public Observer
{
public :
    void handle(int msgid) 
    {
        switch (msgid)
        {
        case 2:
            cout << "Observer2 recv 2 msg " << endl ;
            break;
        case 3:
            cout << "Observer2 recv 3 msg " << endl ;
            break;
        default:
            break;
        }
    }
};

// 第三个观察者实例
class Obsever3 : public Observer
{
public :
    void handle(int msgid) 
    {
        switch (msgid)
        {
        case 3:
            cout << "Observer3 recv 3 msg " << endl ;
            break;
        default:
            break;
        }
    }
};

// 主题类
class Subject
{
public :
    // 给主题增加观察者对象
    void addObserver(Observer *obser , int msgid) 
    {
        _subMap[msgid].push_back(obser) ; 
    }

    // 主题检测发生改变,通知相应的观察者对象处理事件
    void dispatch(int msgid)
    {
        auto it = _subMap.find(msgid) ; 
        if(it != _subMap.end()){
            for (Observer *pObser : it->second)
            {
                pObser->handle(msgid) ; 
            }
        }
    }
private : 
    unordered_map<int , list<Observer* >> _subMap ;  
} ; 

int main() 
{
    Subject subject ; 
    Observer *p1 = new Obsever1() ; 
    Observer *p2 = new Obsever2() ; 
    Observer *p3 = new Obsever3() ; 

    subject.addObserver(p1 , 1) ; 
    subject.addObserver(p1 , 2) ; 
    subject.addObserver(p1 , 3) ; 
    subject.addObserver(p2 , 2) ; 
    subject.addObserver(p3 , 3) ; 

    int msgid = 0 ;
    for(;;)
    {
        cout << "输入消息 msgid : " ; 
        cin>>msgid ; 
        if(msgid == -1) break ; 
        subject.dispatch(msgid) ; 
    }
    return 0 ; 
}

参考文献:
1.C++设计模式 - 单例模式
2.C++设计模式 - 简单工厂,工厂方法和抽象工厂
3.C++设计模式 - 迭代器模式
4.C++设计模式 - 观察者Observer模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值