目录
1 桥接模式定义
2 桥接模式小例子
3 桥接模式的总结
1 桥接模式定义
首先来看看桥接模式的官方定义吧:
桥接模式是将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种结构型模式。
桥接模式的定义确实比较难理解,比较抽象。
下面我们通过一个例子来体会一下桥接模式。
2 桥接模式小例子
假设我们要在windows上编写一个读取硬盘上的图像并显示出来的图像类。因为图像的格式有很多种,它们的读取方式也都不一样。所以我们可以写一个Image父类,并根据不同的格式创建出不同的子类。代码大概就像下面这样:
class Image
{
public:virtual const char* read(string filename) = 0;virtual void display(const char* data) = 0;
};class JPEGImage : public Image
{
public:const char* read(string filename) { cout << "Reading JPEG image from file " << filename << endl; return nullptr; }void display(const char* data)override { cout << "Displaying JPEG image " << endl; }
};class PNGImage : public Image
{
public:const char* read(string filename) { cout << "Reading PNG image from file " << filename << endl; return nullptr; }void display(const char* data)override { cout << "Displaying PNG image " << endl; }
};int main()
{Image* jpg = new JPEGImage();const char* data = jpg->read("image.jpg");jpg->display(data);delete jpg;
}
运行结果如下图所示:
假如现在我们想扩展我们的程序,想让它不仅能够在windows上面运行,并且能够在Linux上面也能运行。图像的格式在每个平台都是一样的,但是在两个平台下图像的显示方法是不一样的。
那么我们可能就会写出JPGImage_Win类、JPGImage_Linux类、PNGImage_Win类、PNGImage_Linux类等等。
如果在需要再增加对一个新平台的支持,就需要为每种图像增加一个针对该平台的类。如果需要再增加一种图像格式,就需要针对每一种平台编写一个类。
这样看起来相当麻烦,因为图像的格式和要显示的平台是两个不同的维度,它们都会产生变化。现在的设计把这两种的变化纠缠在了一起,无论哪一个维度产生了变化都会影响另一个维度。
幸运的是,我们有桥接模式!
我们可以把图像的读取方法还放在Image的子类中实现,但是把平台显示的代码放到另一个类层次中去实现。并在Image类中引用一个平台类。
代码大概长下面这样子:
class Platform
{
public:virtual void display(const char* data) = 0;
};class WindowsPlatform : public Platform
{
public:void display(const char* data) { cout << "Displaying image on Windows platform" << endl; }
};class LinuxPlatform : public Platform
{
public:void display(const char* data) { cout << "Displaying image on Linux platform" << endl; }
};class Image
{
public:Image(Platform* p) : platform(p) {}virtual const char* read(string filename) = 0;void display(const char* data) { platform->display(data); }
private:Platform* platform;
};class JPEGImage : public Image
{
public:JPEGImage(Platform* p) : Image(p) {}const char* read(string filename) { cout << "Reading JPEG image from file " << filename << endl; return nullptr; }
};class PNGImage : public Image
{
public:PNGImage(Platform* p) : Image(p) {}const char* read(string filename) { cout << "Reading PNG image from file " << filename << endl; return nullptr; }
};int main()
{Platform* win = new WindowsPlatform();Image* jpg = new JPEGImage(win);const char* data = jpg->read("image.jpg");jpg->display(data);delete jpg;delete win;return 0;
}
这样就清爽多了,无论将来要扩展平台还是要扩展图片的格式,都可以轻松完成!
有桥接模式真是太幸福啦!
3 桥接模式的总结
我觉得可以这样理解桥接模式:当类里面存在两个或多个独立变化的维度,并且每个维度都会进行扩展,这种情况下就可以使用桥接模式。
桥接模式允许每个维度单独产生变化,而不影响其他维度。