桥接(Bridge)模式的定义如下:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
假如你有一个几何形状(Shape)类, 从它能扩展出两个子类: 圆形(Circle)和方形(Square)。你希望对这样的类层次结构进行扩展以使其包含颜色, 所以你打算创建名为红色(Red)和蓝色(Blue)的形状子类。但是,由于你已有两个子类,所以总共需要创建四个类才能覆盖所有组合,例如蓝色圆形(BlueCircle)和红色方形(RedSquare)。
在层次结构中新增形状和颜色将导致代码复杂程度指数增长。例如添加三角形状,你需要新增两个子类,也就是每种颜色一个;此后新增一种新颜色需要新增三个子类,即每种形状一个。如此以往,情况会越来越糟糕。
解决办法:
问题的根本原因是我们试图在两个独立的维度——形状与颜色——上扩展形状类。这在处理类继承时是很常见的问题。
桥接模式通过将继承改为组合的方式来解决这个问题。具体来说,就是抽取其中一个维度并使之成为独立的类层次,这样就可以在初始类中引用这个新层次的对象,从而使得一个类不必拥有所有的状态和行为。
根据该方法,我们可以将颜色相关的代码抽取到拥有红色和蓝色两个子类的颜色类中,然后在形状类中添加一个指向某一颜色对象的引用成员变量。现在,形状类可以将所有与颜色相关的工作委派给连入的颜色对象。这样的引用就成为了形状和颜色之间的桥梁。此后,新增颜色将不再需要修改形状的类层次,反之亦然。
由于聚合关系建立在抽象层,要求开发者针对抽象化进行设计与编程,能正确地识别出系统中两个独立变化的维度,这增加了系统的理解与设计难度。
现需要提供大中小3种型号的画笔,能够绘制5种不同颜色,如果使用蜡笔,我们需要准备3*5=15支蜡笔,也就是说必须准备15个具体的蜡笔类。而如果使用毛笔的话,只需要3种型号的毛笔,外加5个颜料盒,用3+5=8个类就可以实现15支蜡笔的功能。
实际上,蜡笔和毛笔的关键一个区别就在于笔和颜色是否能够分离。即将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立地变化"。关键就在于能否脱耦。蜡笔的颜色和蜡笔本身是分不开的,所以就造成必须使用15支色彩、大小各异的蜡笔来绘制图画。而毛笔与颜料能够很好的脱耦,各自独立变化,便简化了操作。在这里,抽象层面的概念是:“毛笔用颜料作画”,而在实现时,毛笔有大中小三号,颜料有红绿蓝黑白等5种,于是便可出现3×5种组合。每个参与者(毛笔与颜料)都可以在自己的自由度上随意转换。蜡笔由于无法将笔与颜色分离,造成笔与颜色两个自由度无法单独变化,使得只有创建15种对象才能完成任务。
#include
#include
//实现类接口Color(颜色类)
class Color
{
public:
virtual void bepaint(const std::string&, const std::string&) = 0;
};
//具体实现类Red
class Red : public Color {
public:
void bepaint(const std::string& penType, const std::string& name)
{
std::cout << penType + "红色的" + name + "." << std::endl;
}
};
//具体实现类Green
class Green : public Color {
public:
void bepaint(const std::string& penType, const std::string& name)
{
std::cout << penType + "绿色的" + name + "." << std::endl;
}
};
//抽象类Pen
class Pen {
public:
virtual void draw(const std::string& name) = 0;
void setColor(Color* color)
{
this->color = color;
}
protected:
Color* color;
};
//扩充抽象类BigPen
class BigPen : public Pen {
public:
void draw(const std::string& name) {
std::string penType = "大号毛笔绘制";
this->color->bepaint(penType, name);
}
};
//扩充抽象类SmallPen
class SmallPen : public Pen {
public:
void draw(const std::string& name) {
std::string penType = "小号毛笔绘制";
this->color->bepaint(penType, name);
}
};
//客户端测试类
int main(void) {
Color* color;
Pen* pen;
//这里假装用反射获取
color = (Color*) new Green();
pen = (Pen*) new SmallPen();
pen->setColor(color);
pen->draw("圣诞树");
delete color;
delete pen;
return 0;
}
Abstraction.h:
// Abstraction.h:
#ifndef ABSTRACTION_H_
#define ABSTRACTION_H_
#include
#include "Implementation.h"
// 抽象类: Pen
class Pen {
public:
virtual void draw(std::string name) = 0;
void set_color(Color* color) {
color_ = color;
}
protected:
Color* color_;
};
#endif // ABSTRACTION_H_
RefinedAbstraction.h:
#ifndef REFINED_ABSTRACTION_H_
#define REFINED_ABSTRACTION_H_
#include
#include "Abstraction.h"
// 精确抽象类: BigPen
class BigPen : public Pen {
public:
void draw(std::string name) {
std::string pen_type = "大号钢笔绘制";
color_->bepaint(pen_type, name);
}
};
// 精确抽象类: SmallPencil
class SmallPencil : public Pen {
public:
void draw(std::string name) {
std::string pen_type = "小号铅笔绘制";
color_->bepaint(pen_type, name);
}
};
#endif // REFINED_ABSTRACTION_H_
Implementation.h:
#ifndef IMPLEMENTATION_H_
#define IMPLEMENTATION_H_
#include
#include
// 实现类接口: 颜色
class Color {
public:
virtual void bepaint(std::string pen_type, std::string name) = 0;
};
#endif // IMPLEMENTATION_H_
ConcreteImplementation.h:
#ifndef CONCRETE_IMPLEMENTATION_H_
#define CONCRETE_IMPLEMENTATION_H_
#include
#include "Implementation.h"
// 具体实现类: Red
class Red : public Color {
public:
void bepaint(std::string pen_type, std::string name) override {
std::cout << pen_type << "红色的" << name << "." << std::endl;
}
};
// 具体实现类: Green
class Green : public Color {
public:
void bepaint(std::string pen_type, std::string name) override {
std::cout << pen_type << "绿色的" << name << "." << std::endl;
}
};
#endif // CONCRETE_IMPLEMENTATION_H_
main.cpp:
#include "ConcreteImplementation.h"
#include "RefinedAbstraction.h"
int main() {
// 客户端根据运行时参数获取对应的Color和Pen
Color* color = new Red();
Pen* pen = new SmallPencil();
pen->set_color(color);
pen->draw("太阳");
delete color;
delete pen;
}
运行结果:
$g++ -g main.cpp -o bridge -std=c++11
$./bridge
小号铅笔绘制红色的太阳.
用Python实现
# 抽象规格类
class Size(object):
def __init__(self, size):
self.color = None
self._size = size
# match_color 作为桥接, 各自的变化, 不影响其他分类
def match_color(self, color):
self.color = color
def produce(self):
print(f"生产 规格为: {self._size} 颜色为: {self.color.color()} 的笔")
# 大号规格,具体规格类,继承抽象规格类
class BigSize(Size):
def __init__(self):
super(BigSize, self).__init__('大号')
# 中号
class MiddleSize(Size):
def __init__(self):
super(MiddleSize, self).__init__('中号')
# 小号
class SmallSize(Size):
def __init__(self):
super(SmallSize, self).__init__('小号')
# 抽象颜色类
class Color(object):
def __init__(self, color):
self._color = color
def color(self):
return self._color
# 红色
class RedColor(Color):
def __init__(self):
super(RedColor, self).__init__('红色')
# 蓝色
class BlueColor(Color):
def __init__(self):
super(BlueColor, self).__init__('蓝色')
# 黄色
class YellowColor(Color):
def __init__(self):
super(YellowColor, self).__init__('黄色')
if __name__ == "__main__":
red = RedColor()
blue = BlueColor()
yellow = YellowColor()
big_size = BigSize()
big_size.match_color(red)
big_size.produce()
big_size.match_color(blue)
big_size.produce()
big_size.match_color(yellow)
big_size.produce()
middle_size = MiddleSize()
middle_size.match_color(red)
middle_size.produce()
middle_size.match_color(blue)
middle_size.produce()
middle_size.match_color(yellow)
middle_size.produce()
small_size = SmallSize()
small_size.match_color(blue)
small_size.produce()
small_size.match_color(red)
small_size.produce()
small_size.match_color(yellow)
small_size.produce()
#抽象类:人
class people:
def set_skill(self,skill):
self.skill=skill
def perform_skill(self):
pass
#具体抽象类:花匠
class hua_j(people):
def perform_skill(self):
print('我是花匠')
self.skill.perform_skill()
#具体抽象类:木匠
class mu_j(people):
def perform_skill(self):
print('我是木匠')
self.skill.perform_skill()
#具体抽象类:铁匠
class tie_j(people):
def perform_skill(self):
print('我是铁匠')
self.skill.perform_skill()
#功能类,也是实现类
class skill:
def perform_skill(self):
pass
#具体功能类,也是具体实现类 种花
class skill_hua(skill):
def perform_skill(self):
print('我会种花')
#具体功能类,也是具体实现类 做木桌子
class skill_mu:
def perform_skill(self):
print('我会做木桌子')
#具体功能类,也是具体实现类 做铁桌子
class skill_tie:
def perform_skill(self):
print('我会做铁桌子')
#具体功能类,也是具体实现类 做老师
class skill_teacher:
def perform_skill(self):
print('我会做老师,可以教学生')
#具体功能类,也是具体实现类 做家具
class skill_jj:
def perform_skill(self):
print('我会做家具')
def main():
h=hua_j() #花匠
m=mu_j() #木匠
t=tie_j() #铁匠
sh=skill_hua()# 本事:会种花
sm=skill_mu() #本事:会做木头桌子
st=skill_tie() #本事:会做铁桌子
s_t=skill_teacher() #本事:会教学生
s_jj=skill_jj() #本事:会做家具
h.set_skill(sh) #给花匠set种花的本事
h.perform_skill() #花匠 种花
h.set_skill(s_t) #给花匠set做老师的本事
h.perform_skill() #花匠教学生
print('=============')
m.set_skill(sm) #给木匠set 做木桌子的本事
m.perform_skill() #木匠 做木桌子
m.set_skill(s_t) #给木匠set做老师的本事
m.perform_skill() #木匠教学生
m.set_skill(s_jj) #给木匠set做家具的本事
m.perform_skill() #木匠做家具
print('=============')
t.set_skill(st) #给木匠set 做木桌子的本事
t.perform_skill() #木匠 做木桌子
t.set_skill(s_t) #给木匠set做老师的本事
t.perform_skill() #木匠教学生
t.set_skill(s_jj) #给木匠set做家具的本事
t.perform_skill() #木匠做家具
if __name__ == '__main__':
main()