在軟件設計中,如果責任劃分不清晰,需求的變化時,子類會急劇膨脹,代碼會大量重複。此時,劃分責任是最關鍵的做法。
定義
橋模式將“抽象部分”與“實現部分”分離,使它們獨立的變化。
實例
先看下面代碼存在的問題。(子類膨脹,重複代碼)
在PC平臺和Mobile平臺分別實現文本和圖片的生成和發送。
消息的基類如下:
class Messager
{
public:
virtual void SendText(string text) = 0;
virtual void SendPicture(string Image) = 0;
virtual void PlaySound() = 0;
virtual void DrawText() = 0;
virtual void DrawPicture() = 0;
virtual ~Messager(){}
};
PC平臺的實現如下:
//PC平臺
class PCMessager:public Messager
{
public:
virtual void PlaySound() override {}
virtual void DrawText() override {}
virtual void DrawPicture() override {}
virtual ~PCMessager(){}
};
//精簡版
class PCMessagerLite :public PCMessager
{
public:
virtual void SendText(string text) override
{
PCMessager::DrawText();
}
virtual void SendPicture(string Image) override
{
PCMessager::DrawPicture();
}
virtual ~PCMessagerLite() {}
};
//完美版
class PCMessagerPerfect :public PCMessager
{
public:
virtual void SendText(string text) override
{
PCMessager::PlaySound();
PCMessager::DrawText();
}
virtual void SendPicture(string Image) override
{
PCMessager::PlaySound();
PCMessager::DrawPicture();
}
virtual ~PCMessagerPerfect(){}
};
Mobile平臺的實現如下:
//Mobile平臺
class MobileMessager :public Messager
{
public:
virtual void PlaySound()override {}
virtual void DrawText() override {}
virtual void DrawPicture() override {}
virtual ~MobileMessager(){}
};
//精簡版
class MobileMessagerLite :public MobileMessager
{
public:
virtual void SendText(string text) override
{
MobileMessager::DrawText();
}
virtual void SendPicture(string Image) override
{
MobileMessager::DrawPicture();
}
virtual ~MobileMessagerLite(){}
};
//完美版
class MobileMessagerPerfect :public MobileMessager
{
public:
virtual void SendText(string text) override
{
MobileMessager::PlaySound();
MobileMessager::DrawText();
}
virtual void SendPicture(string Image) override
{
MobileMessager::PlaySound();
MobileMessager::DrawPicture();
}
virtual ~MobileMessagerPerfect() {}
};
上述代碼中存在大量的重複代碼,原因是將messager的兩個方向上的變化混在了一起,使用了繼承而不是組合的方式組織代碼。
下面使用橋模式改進代碼:
平臺實現:
class MessagerImp
{
public:
virtual void PlaySound() = 0;
virtual void DrawText() = 0;
virtual void DrawPicture() = 0;
virtual ~MessagerImp() {}
};
//PC平臺
class PCMessagerImp :public MessagerImp
{
public:
virtual void PlaySound()override {}
virtual void DrawText() override {}
virtual void DrawPicture() override {}
virtual ~PCMessagerImp() {}
};
//Mobile平臺
class MobileMessagerImp :public MessagerImp
{
public:
virtual void PlaySound()override {}
virtual void DrawText() override {}
virtual void DrawPicture() override {}
virtual ~MobileMessagerImp() {}
};
業務實現:
class Messager
{
public:
virtual void SendText(string text) = 0;
virtual void SendPicture(string Image) = 0;
virtual ~Messager(){}
protected:
MessagerImp *messagerImp;
};
//精簡版
class MessagerLite: public Messager
{
public:
virtual void SendText(string text) override
{
messagerImp->DrawText();
}
virtual void SendPicture(string Image) override
{
messagerImp->DrawPicture();
}
virtual ~MessagerLite() {}
};
//完美版
class MessagerPerfect: public Messager
{
public:
virtual void SendText(string text) override
{
messagerImp->PlaySound();
messagerImp->DrawText();
}
virtual void SendPicture(string Image) override
{
messagerImp->PlaySound();
messagerImp->DrawPicture();
}
virtual ~MessagerPerfect() {}
};
橋模式的類圖如下:
總結
橋模式使用“對象間的組合關係”解耦了抽象和實現兩個維度的變化。