0
点赞
收藏
分享

微信扫一扫

设计模式之桥模式(Bridge)

目录

前言

在学习侯捷老师的有关设计模式的课程(李建忠老师主讲)中,老师对23种设计模式的有自己的划分,如下。所以老师讲解是按照这种顺序讲解。
在这里插入图片描述
单一职责:
在这里插入图片描述

Bridge设计模式

1.模式动机

由于某些类型的固有的实现逻辑,使得它们具有两个变化的维度,乃至多个纬度的变化。
所以Bridge模式的动机就是应对“多维度的变化

看文字描述表枯燥,下面举几个例子:

  1. 商城系统中的电脑分类:如电脑类型+电脑品牌,这是两个维度的变化。
    在这里插入图片描述
  2. 图形形状+颜色填充两种变化的维度
    在这里插入图片描述

下面是桥模式的实际看法场景:

在这里插入图片描述
参考至:参考

下面给一个具体的案例:

2.示例1

先看代码,后面解释会清楚点。

#include <iostream>
using namespace std;

//实现抽象
class MessagerImp{
public:
	virtual void PlaySound() = 0;
	virtual void DrawShape() = 0;
	virtual void WriteText() = 0;
	virtual void Connect() = 0;

	virtual ~MessagerImp(){}
};

//平台实现
class PCMessagerImp : public MessagerImp{//PC平台
public:

	virtual void PlaySound(){
		//**********
		cout << "PC::PlaySound ,播放声音." << endl;
	}
	virtual void DrawShape(){
		//**********
		cout << "PC::DrawShape ,画图形." << endl;
	}
	virtual void WriteText(){
		//**********
		cout << "PC::WriteText ,写文本." << endl;
	}
	virtual void Connect(){
		//**********
		cout << "PC::Connect ,登录连接." << endl;
	}
};
class MobileMessagerImp : public MessagerImp{//PC平台
public:
	virtual void PlaySound(){
		//**********
		cout << "Mobile::PlaySound ,播放声音." << endl;
	}
	virtual void DrawShape(){
		//**********
		cout << "Mobile::DrawShape ,画图形." << endl;
	}
	virtual void WriteText(){
		//**********
		cout << "Mobile::WriteText ,写文本." << endl;
	}
	virtual void Connect(){
		//**********
		cout << "Mobile::Connect ,登录连接." << endl;
	}
};



//业务功能抽象
class Messager{
protected:
	MessagerImp* messagerImp;//拿着实现(MessagerImp)的基类指针
	Messager(MessagerImp* _messagerImp) : messagerImp(_messagerImp){}

public:
	virtual void Login(string username, string password) = 0;
	virtual void SendMessage(string message) = 0;
	virtual void SendPicture() = 0;

	virtual ~Messager(){}
};

//业务实现
class MessagerLite :public Messager {//Lite
public:
	MessagerLite(MessagerImp* _messagerImp) : Messager(_messagerImp){}
	virtual void Login(string username, string password){

		cout << "Lite::Login , 登录..." << endl;
		messagerImp->Connect();
		//........
	}
	virtual void SendMessage(string message){

		cout << "Lite::SendMessage , 发送登录消息..." << endl;
		messagerImp->WriteText();
		//........
	}
	virtual void SendPicture(){
		cout << "Lite::SendMessage , 发送图片..." << endl;
		messagerImp->DrawShape();
		//........
	}
};

class MessagerPerfect :public Messager {
public:
	MessagerPerfect(MessagerImp* _messagerImp) : Messager(_messagerImp){}

	virtual void Login(string username, string password){

		cout << "Perfect::Login , 登录..." << endl;
		messagerImp->PlaySound();
		//********
		messagerImp->Connect();
		//........
	}
	virtual void SendMessage(string message){

		cout << "Perfect::SendMessage , 发送登录消息..." << endl;
		messagerImp->PlaySound();
		//********
		messagerImp->WriteText();
		//........
	}
	virtual void SendPicture(){

		cout << "Perfect::SendMessage , 发送图片..." << endl;
		messagerImp->PlaySound();
		//********
		messagerImp->DrawShape();
		//........
	}
};

int main()
{

	Messager* mes = new MessagerLite(new PCMessagerImp);//生成精简版(Lite)Message,在PC平台下
	mes->Login("xxx","123");
	mes->SendMessage("success");
	mes->SendPicture();

	cout << "-------------------------------" << endl;

	Messager* mes1 = new MessagerPerfect(new PCMessagerImp);//生成完美版(Perfector)Message,在PC平台下
	mes1->Login("xxx", "123");
	mes1->SendMessage("success");
	mes1->SendPicture();


	system("pause");
	return 0;
}

有一个Message类,有Login、SendMessage、SendPicture3种抽象方法,精简版(Lite)和完美版(Perfector)会对这3种抽象方法进行相应的覆写(这里为了方便,只会对Perfector版加入一个播放声音的操作)。

又在不同的平台(PC、Mobile)下,部分操作PlaySound、DrawShape、WriteText、Connect不相同(这里的操作定是和Message类相关,不然就可以把二者独立开,和Bridge模式便毫无关系)。如下图所示,就有两个不同的维度

在这里插入图片描述
前面已经说过,桥模式就是应对这样多维度的变化。具体做法就是:

我们通过让Message得到MessageImp的指针(多态),这样,客户程序就可以组合Lite、PerfectorPC、Mobile。并且,可以很好的应对未来的扩展,比如MessageImp可以扩展一个Mac

注: MessageMessageImp均是接口。

在这里插入图片描述

另外,你在设计时,也许可能会做如下设计:

首先Message类,将业务实现方法:Login、SendMessage、SendPicture和不同平台下的方法:PlaySound、DrawShape、WriteText、Connect均放在这里。如下

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

    virtual void PlaySound()=0;
    virtual void DrawShape()=0;
    virtual void WriteText()=0;
    virtual void Connect()=0;
    
    virtual ~Messager(){}
};

然后通过继承的方式来做:
MobileMessage、PCMessage覆写不同平台下的方法:PlaySound、DrawShape、WriteText、Connect
接着在MobilePerfector、MobileLite、PCPerfector、PCPerfector分别覆写业务Login、SendMessage、SendPicture
示例图如下:
在这里插入图片描述
假设现在我加一个Mac平台,那么就要增加3个类,如果是10个类呢,就是10*3 = 30个类,而用桥模式只要10个即可。可以想象这种方法的可扩展性有多差。

3.示例2:图形和颜色

下面实现在模式动机中给的例子:图形形状和颜色填充
在这里插入图片描述
直接给代码:

#include <iostream>
using namespace std;

//实现抽象
class Color
{
public:
	virtual void putColor() = 0;
	virtual ~Color(){}
};
class RedColor : public Color
{
public:
	virtual void putColor()
	{
		//...
		cout << "上红色" << endl;
		//...
	}
};
class BullColor : public Color
{
public:
	virtual void putColor()
	{
		//...
		cout << "上蓝色" << endl;
		//...
	}
};
class YellowColor : public Color
{
public:
	virtual void putColor()
	{
		//...
		cout << "上黄色" << endl;
		//...
	}
};

class Shape
{
protected:
	Color* color;
	Shape(Color* _color) :color(_color){}
public:
	virtual void drawShape() = 0;

	virtual ~Shape(){};
};

class Rectangle : public Shape
{

public:
	Rectangle(Color* _color) :Shape(_color){}

	virtual void drawShape()
	{
		cout << "矩形" << "->";
		color->putColor();
	}
};
class Circle : public Shape
{

public:
	Circle(Color* _color) :Shape(_color){}

	virtual void drawShape()
	{
		cout << "圆形" << "->";
		color->putColor();
	}
};

class Triangle : public Shape
{

public:
	Triangle(Color* _color) :Shape(_color){}

	virtual void drawShape()
	{
		cout << "三角形" <<  "->";
		color->putColor();
	}
};

int main()
{
	Shape* sh = new Rectangle(new BullColor);
	sh->drawShape();

	sh = new Circle(new YellowColor);
	sh->drawShape();



	system("pause");
	return 0;
}

4.模式定义

在这里插入图片描述

注: 什么叫将抽象和实现分离呢?

  • 这里的抽象指的并不是抽象类或者接口,而是被抽象出来的一套“类库”,它只包含骨架代码,真正的业务逻辑需要委托给定义中的“实现”来完成
  • 我们这里所说的实现也绝非接口的实现类,而是一套独立的“类库”
  • “抽象”和“实现”独立开发,通过对象之间的组合关系,组装在一起。

上述描述参考:
https://blog.csdn.net/qq_35423154/article/details/111085839

5.模式结构

在这里插入图片描述
Abstraction就像示例中的MessageShape
Implementor就像示例中的MessageImpColor

6.要点总结

  • Bridge模式使用“对象间的组合关系”解耦了抽象和实现(抽象出骨架代码,在骨架代码中某些步骤在实现中完成)之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。所谓抽象和实现沿着各自纬度的变化,即“子类化”它们。

  • Bridge模式有时候类似于多继承方案(就像在示例2中,生成一个红色矩形,可以看成是同时继承Shape类和Color),但是多继承方案往往违背单一职责原则(即一个类只有一个变化的原因),复用性比较差。Bridge模式是比多继承方案更好的解决方法

  • Bridge模式的应用一般在“两个非常强的变化维度”,有时一个类也有多于两个的变化维度,这时可以使用Bridge的扩展模式(桥模式就是解决多维度的问题)。

举报

相关推荐

0 条评论