C++设计模式学习笔记 桥模式(单一职责)

一、普通写法

变化的方向越多,子类的数量就会越庞大,假设变化方向为n,具体变化子类为m,则总的类数为1+n + m*n。

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

class Image{

};


// 抽象基类
class Messager{
public:
    virtual void Login(string username, string password) = 0;
    virtual void SendMessage(string message) = 0;
    virtual void SendPicture(Image image) = 0;

    virtual void PlaySound() = 0;
    virtual void DrawShape() = 0;
    virtual void WriteText() = 0;
    virtual void Connect() = 0;

    virtual ~Messager(){}
};

// 平台实现
class PCMessagerBase : public Messager{
public:
    virtual void PlaySound(){

    }

    virtual void DrawShape(){

    }

    virtual void WriteText(){

    }

    virtual void Connect(){

    }
};

class MobileMessagerBase : public Messager{
public:
    virtual void PlaySound(){

    }

    virtual void DrawShape(){

    }

    virtual void WriteText(){

    }

    virtual void Connect(){
        
    }
};


// 业务抽象
class PCMessagerLite : public PCMessagerBase{
public:

    virtual void Login(string username,string password){
        PCMessagerBase::Connect();
    }

    virtual void SendMessage(string message){
        PCMessagerBase::WriteText();
    }

    virtual void SendPicture(Image image){
        PCMessagerBase::DrawShape();
    }
    
};

class PCMessagerPerfect : public PCMessagerBase {
    public:

    virtual void Login(string username,string password){  
        PCMessagerBase::PlaySound();
        PCMessagerBase::Connect();
    }

    virtual void SendMessage(string message){
        PCMessagerBase::PlaySound();
        PCMessagerBase::WriteText();
    }

    virtual void SendPicture(Image image){
        PCMessagerBase::PlaySound();
        PCMessagerBase::DrawShape();
    }
};

class MobileMessagerLite : public MobileMessagerBase{
public:

    virtual void Login(string username,string password){
        MobileMessagerBase::Connect();
    }

    virtual void SendMessage(string message){
        MobileMessagerBase::WriteText();
    }

    virtual void SendPicture(Image image){
        MobileMessagerBase::DrawShape();
    }
};

class MobileMessagerPerfect : public MobileMessagerBase {
public:

    virtual void Login(string username,string password){  
        MobileMessagerBase::PlaySound();
        MobileMessagerBase::Connect();
    }

    virtual void SendMessage(string message){
        MobileMessagerBase::PlaySound();
        MobileMessagerBase::WriteText();
    }

    virtual void SendPicture(Image image){
        MobileMessagerBase::PlaySound();
        MobileMessagerBase::DrawShape();
    }
};

void Process(){
    // 编译时装配
    Messager* msg = new MobileMessagerPerfect();
    Messager* msg_pc = new PCMessagerLite();
}

int main(){

    Process();
    return 0;
}

二、桥模式

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

class Image{

};

// 具体功能虚基类
class MessagerImpl{
public:
    virtual void PlaySound() = 0;
    virtual void DrawShape() = 0;
    virtual void WriteText() = 0;
    virtual void Connect() = 0;

    virtual ~MessagerImpl(){}
};


// 抽象基类
class Messager{
protected:
    MessagerImpl* messagerImpl;
public:
    Messager(MessagerImpl* msg) : messagerImpl(msg){}

    virtual void Login(string username, string password) {}
    virtual void SendMessage(string message) {}
    virtual void SendPicture(Image image) {}

    virtual ~Messager(){}
};

// 平台实现 n
class PCMessagerImpl : public MessagerImpl {
public:
    virtual void PlaySound(){

    }

    virtual void DrawShape(){

    }

    virtual void WriteText(){

    }

    virtual void Connect(){

    }
};

class MobileMessagerImpl : public MessagerImpl{
public:
    virtual void PlaySound(){

    }

    virtual void DrawShape(){

    }

    virtual void WriteText(){

    }

    virtual void Connect(){
        
    }
};


// 业务抽象 m
// 类的数目:1 + n + m
class MessagerLite : public Messager{
public:

    virtual void Login(string username,string password){
        messagerImpl->Connect();
    }

    virtual void SendMessage(string message){
        messagerImpl->WriteText();
    }

    virtual void SendPicture(Image image){
        messagerImpl->DrawShape();
    }
    
};

class MessagerPerfect : public Messager {
    public:

    virtual void Login(string username,string password){  
        messagerImpl->PlaySound();
        messagerImpl->Connect();
    }

    virtual void SendMessage(string message){
        messagerImpl->PlaySound();
        messagerImpl->WriteText();
    }

    virtual void SendPicture(Image image){
        messagerImpl->PlaySound();
        messagerImpl->DrawShape();
    }
};

void Process(){
    // 运行时装配
    MessagerImpl* msgImpl = new PCMessagerImpl();
    Messager* msg = new Messager(msgImpl);

    MessagerImpl* msgImpl_mobile = new MobileMessagerImpl();
    Messager* msg_mobile = new Messager(msgImpl_mobile);
}

int main(){

    Process();
    return 0;
}

在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任。 因此,桥模式应此而生。

桥模式的动机:

由于某些类型的固有的实现逻辑,使得他们具有两个变化的维度,乃至多个维度的变化。

如何应对这种“多种维度的变化”?如何利用面向对象技术使得类型可以轻松地沿着两个乃至多个变化方向,而不引入额外的复杂度?

桥模式的定义:

将抽象部分(业务功能)与实现部分(平台实现)分离,使得他们都可以独立地变化。《设计模式》GoF

总结:

桥模式使用“对象间的组合关系”解耦了抽象与实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化,所谓抽象和实现沿着各自维度的变化,即“子类化”它们。

桥模式有时候类似于多种继承方案,但是多继承方案往往违背单一职责原则(即一个类只能有一个变化的原因),复用性比较差。桥模式是比多继承方案更好的解决方法。

桥模式的应用一般在“两个非常强的变化维度”,有时一个类页游多于两个的变化维度,这时可以使用桥模式的扩展模式。


版权声明:本文为qq_32285693原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。