设计模式的理解:桥模式 Bridge

         当一种抽象有多种实现时通常用继承来实现他们。桥模式的设计和装饰模式 有一定的相似之处,都是通过组合来解决继承的滥用问题。现有一个需求,将一个项目分成普通用户版和VIP版,该项目要同时支持WINDOW10 和手机版本。VIP版在当登录,发送消息时会有铃声提示和播放些动画,而普通用户版没有。基础功能抽象类如下:

class  Base {
 public:
 virtual void login(string userid,string password)=0;
 virtual void sendMessage(string message)=0;
 virtual void playSound()=0;
 virtual void playAnimation()=0;
}

在上述抽象类的设计中,由于 Windows10 和 手机版本的接口不一样,继承Base 类需要实现 playSound 和 playAnimation。而vip版和用户版是功能的扩展需实现login和sendMessage

class  Base {
 public:
 virtual void login(string userid,string password)=0;
 virtual void sendMessage(string message)=0;
 virtual void playSound()=0;
 virtual void playAnimation()=0;
};


class Windows10Base : public Base{
 public :
 virtual void playSound(){
   //电脑版播放声音
 }
 virtual void playAnimation(){
   //电脑版播放动画
 }
 virtual void login(string userid,string pwd){
  // login()
 }
 virtual void sendMessage(string userid,string pwd){
  //  sendMessage()
 }
};
class MobileBase : public Base{
 public :
 virtual void playSound(){
   //手机版播放声音
 }
 virtual void playAnimation(){
   //手机版播放动画
 }
  virtual void login(string userid,string pwd){
  // login()
 }
 virtual void sendMessage(string userid,string pwd){
  //  sendMessage()
 }
};

class Windows10VIP : public Windows10Base {
 public :
 virtual void login(string userid,string pwd){
  Windows10Base::playSound();
  Windows10Base::playAnimation();
  // login()
 }
 virtual void sendMessage(string userid,string pwd){
  Windows10Base::playSound();
  Windows10Base::playAnimation();
  //  sendMessage()
 }
};
class MobileVIP : public MobileBase {
 public :
  virtual void login(string userid,string pwd){
  MobileBase ::playSound();
  MobileBase ::playAnimation();
  // login()
 }
 virtual void sendMessage(string userid,string pwd){
  MobileBase ::playSound();
  MobileBase ::playAnimation();
  //  sendMessage()
 }
};

此设计方式是不利于扩展的,当前情况是支持两个系统的功能,用户等级分为两个就要有 4个派生类。假如业务将Vip等级进行细化,细化成 VIP1,VIP2,VIP3 等,那么每个等级不得同时去继承不同系统的类吗。假如需要支持Window 7 ,Window10,手机等 n 个不同的系统,业务要求用户等级需细分成 m 个不同的等级,按照上述的方法就会建立  m* n 个派生类。

如果应用桥模式,那么只需要新建 m+ n 个派生类,当进行系统扩展时只需要新增1个类,当VIP等级进行扩展时,也只需要新增1个类就行。

桥模式,将抽象部分与它的实现部分分离。反应出来的设计思想是,当抽象类中的纯虚函数应按照不同维度进行分离,分别继承,通过内成员指针将不同维度的方法关联在一起。换句话说,上述的需求分成 “可支持的系统”维度 和 “VIP等级” 维度。这两个不同维度中需实现的方法不一致时就不应该将这些抽象方法放一起。

class SystemBase {
 public :
 virtual void playSound()=0;
 virtual void playAnimation()=0;
};
class UserLevelBase {
 SystemBase  * systemBase;
 public :
 UserLevelBase (s):systemBase(s){}
 virtual void login(string userid,string pwd)=0;
 virtual void sendMessage(string userid,string pwd)=0;
};

class NormalLevel :public UserLevelBase  {
 public :
 NormalLevel (SystemBase *s):UserLevelBase (s){}
 virtual void login(string userid,string pwd){
  // login()
 }
 virtual void sendMessage(string userid,string pwd){
  //  sendMessage()
 }
};
class VIPLevelfirst : public UserLevelBase  {
 public :
  VIPLevelfirst (SystemBase *s):UserLevelBase (s){}
  virtual void login(string userid,string pwd){
    systemBase->playSound();
    systemBase->playAnimation();
    // login()
  }
 virtual void sendMessage(string userid,string pwd){
    systemBase->playSound();
    systemBase->playAnimation();
    //  sendMessage()
 }
};
class MobileBase : public SystemBase{
 public :
 virtual void playSound(){
   //手机版播放声音
 }
 virtual void playAnimation(){
   //手机版播放动画
 }
};
class Windows10Base : public SystemBase{
 public :
 virtual void playSound(){
   //电脑版播放声音
 }
 virtual void playAnimation(){
   //电脑版播放动画
 }
};


//----------------------------------------
void main(){
 
 SystemBase * mobileSystem = new MobileBase ();
 SystemBase * PCSystem  = new  Windows10Base ();
 VIPLevelfirst  vipuserpc(PCSystem); //Windows10 的VIP用户
 NormalLevel  usermobile(PCSystem); //手机的普通用户
}

 

第一种设计模式不利于扩展,需要的派生类时不同维度功能的个数的乘积,而第二种将不同维度的抽象方法拆分成变成各自的抽象类,其需要的派生类是不同维度功能的个数的和。

桥模式,将不同维度的抽象方法进行分离,用抽象指针或者引用将其抽象类相关联

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值