设计模式--单一职责模式之桥模式

“单一职责”模式

单一职责模式出现的原由是:在软件设计中,如果出现责任划分不清楚,使用继承得到的结果往往会随需求的变化,子类急剧膨胀,同时充斥重复代码,这个时候的关键就是划清责任。

桥模式

A:说明

桥模式的动机:由于某些类型的固有的实现逻辑,使得他们具有多个变化得维度,带来子类膨胀和重复代码的问题。

B:例子(不同平台的邮件信箱收发邮件的实现)

1)首先我们想到是一堆的功能接口,将其所有功能接口放到一个纯虚类中,作为基类。同时有想到支持的平台主题,包括PC和Mobile,并继承接口定义的基类,并实现相关平台操作的接口(播放声音,画线等等)。并根据需求推出平台的不同版本,具体UML和代码如下:

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(){
        //==========
    }
};

//业务抽象
//PC经典版
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();
        //........
    }
};


//PC完美版
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 *m = new MobileMessagerPerfect();
}

上述的设计也存在缺陷,主要集中在,后期需求变大,子类的数量也会剧增,同时也存在结构上的代码重复(PCMessagerLite ::Login和MobileMessagerLite::Login 在代码结构逻辑上存在重复)。

2)根据设计原则:组合优于继承。重构代码如下:

class PCMessagerLite  {
protected:
     Messager* messager; //= new PCMessagerBase();
public:
    virtual void Login(string username, string password){  
        messager->Connect();
        //........
    }
    virtual void SendMessage(string message){
        messager->WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        messager->DrawShape();
        //........
    }
};

//手机经典版
class MobileMessagerLite {
protected:
     Messager* messager; //= new MobileMessagerBase();
public:
    virtual void Login(string username, string password){
        messager->Connect();
        //........
    }
    virtual void SendMessage(string message){
        messager->WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        messager->DrawShape();
        //........
    }
};

上述代码修改由编译时装配改为运行时装配,修改后的PcMessagerLite和MobileMessagerLite一模一样,可以设计为同一个类。类似的有关Perfect类也可以这样操作。

//经典版
class MessagerLite  {
protected:
    Messager* messager; //new PCMessagerBase() / MobileMessagerBase()
public:
    virtual void Login(string username, string password){  
        messager->Connect();
        //........
    }
    virtual void SendMessage(string message){
        messager->WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        messager->DrawShape();
        //........
    }
};

//完美版
class MessagerPerfect{
protected:
    Messager* messager;// new PCMessagerBase() / MobileMessagerBase()
public:
    virtual void Login(string username, string password){
        messager->PlaySound();
        //********
        messager->Connect();
        //........
    }
    virtual void SendMessage(string message){
        messager->PlaySound();
        //********
        messager->WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        messager->PlaySound();
        //********
        messager->DrawShape();
        //........
    }
};

上述的代码信息的会发现编译不会通过。 原因是Messager是个纯虚基类,而PcMessagerBase和MobileMessagerBase并没有全部实现所有纯虚函数,同样MessagerLite和MessagerPerfect也没有。造成这种原因的是纯虚基类里定义了多个变化/功能的维度。因此就需要拆分纯虚基类。代码如下

class Messager{
public:
    Messager(){}
    virtual void Login(string username, string password)=0;
    virtual void SendMessage(string message)=0;
    virtual void SendPicture(Image image)=0;

    virtual ~Messager(){}
};

class MessagerImp{
public:
    MessagerImp(){}
    virtual void PlaySound()=0;   //往下接口,各个平台的实现是不一样的
    virtual void DrawShape()=0;
    virtual void WriteText()=0;
    virtual void Connect()=0;
    virtual ~MessagerImp(){} 
};

//平台主体类实现
class PCMessagerImp : public MessagerImp{
public:
    virtual void PlaySound(){
        //**********
    }
    virtual void DrawShape(){
        //**********
    }
    virtual void WriteText(){
        //**********
    }
    virtual void Connect(){
        //**********
    }
};

class MobileMessagerImp : public MessagerImp{
public:
    virtual void PlaySound(){
        //==========
    }
    virtual void DrawShape(){
        //==========
    }
    virtual void WriteText(){
        //==========
    }
    virtual void Connect(){
        //==========
    }
};

//经典版
class MessagerLite : public Messager {
protected:
    MessagerImp* messagerImp; //new PCMessagerBase() / MobileMessagerBase()
public:
    virtual void Login(string username, string password){  
        messagerImp->Connect();
        //........
    }
    virtual void SendMessage(string message){
        messagerImp->WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        messagerImp->DrawShape();
        //........
    }
};

//完美版
class MessagerPerfect: public Messager{
protected:
    MessagerImp* messagerImp;// new PCMessagerImp() / MobileMessagerImp()
public:
    virtual void Login(string username, string password){
        messagerImp->PlaySound();
        //********
        messagerImp->Connect();
        //........
    }
    virtual void SendMessage(string message){
        messagerImp->PlaySound();
        //********
        messager->WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        messagerImp->PlaySound();
        //********
        messagerImp->DrawShape();
        //........
    }
};

3)再根据马丁.福勒 重构原则里,提到需要将子类里重复的变量往上提,代码如下:

class Messager{
protected:
    MessagerImp* _imp;
public:
    Messager(MessagerImp* imp):_imp(imp){}
    virtual void Login(string username, string password)=0;
    virtual void SendMessage(string message)=0;
    virtual void SendPicture(Image image)=0;

    virtual ~Messager(){}
};

class MessagerImp{
public:
    MessagerImp(){}
    virtual void PlaySound()=0;   //往下接口,各个平台的实现是不一样的
    virtual void DrawShape()=0;
    virtual void WriteText()=0;
    virtual void Connect()=0;
    virtual ~MessagerImp(){} 
};

//平台主体类实现
class PCMessagerImp : public MessagerImp{
public:
    virtual void PlaySound(){
        //**********
    }
    virtual void DrawShape(){
        //**********
    }
    virtual void WriteText(){
        //**********
    }
    virtual void Connect(){
        //**********
    }
};

class MobileMessagerImp : public MessagerImp{
public:
    virtual void PlaySound(){
        //==========
    }
    virtual void DrawShape(){
        //==========
    }
    virtual void WriteText(){
        //==========
    }
    virtual void Connect(){
        //==========
    }
};

//经典版
class MessagerLite : public Messager {
public:
    MessagerLite(MessagerImp* imp):Messager(imp){}
    ~MessagerLite(){}
    virtual void Login(string username, string password){  
        _imp->Connect();
        //........
    }
    virtual void SendMessage(string message){
        _imp->WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        _imp->DrawShape();
        //........
    }
};

//完美版
class MessagerPerfect: public Messager{
public:
    MessagerPerfect(MessagerImp* imp):Messager(imp){}
   ~MessagerPerfect(){}
    virtual void Login(string username, string password){
        _imp->PlaySound();
        //********
        _imp->Connect();
        //........
    }
    virtual void SendMessage(string message){
        _imp->PlaySound();
        //********
        _imp->WriteText();
        //........
    }
    virtual void SendPicture(Image image){
        _imp->PlaySound();
        //********
        _imp->DrawShape();
        //........
    }
};

void Process(){
   //运行时装配
   MessagerImp* pc = new PcMobileMessagerImp();
   Messager* msgLite = new MessagerLite(pc);
    
}

上述的过程就是桥模式,回顾前面的,我们这个需求有两个变化的维度,一个是平台实现的变化,一个是业务功能的变化。这俩个变化的方向带动行为的多态的实现应该也是往不同方向发展,不应该放到同一个类中。这就桥模式的思想

C:总结

1,根据设计模式的原则:将抽象部分(业务功能)和实现部分(平台实现)分离,使它们都可以独立的变化。结构UML如下:

红框里是稳定的部分,蓝框是变化的部分,设计模式将稳定的部分和变化的部分分离开。

2,桥模式是使用“对象间的组合关系”解耦了抽象和实现之间的固有绑定关系,使其沿着各自维度变化。一般用在“多个非常强的变化维度”时

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值