设计模式之桥接模式
设计模式之桥接模式
引入
初始方案
场景一:
Sunny 软件公司欲开发一个跨平台图像浏览系统,要求该系统能够显示 BMP、JPG、GIF、PNG 等多种格式的文件,并且能够在
Windows、Linux、Unix 等多个操作系统上运行。
系统首先将各种格式的文件解析为像素矩阵( Matrix ),然后将像素矩阵显示在屏幕上,在不同的操作系统中可以调用不同的绘制函
数来绘制像素矩阵。
系统需具有较好的扩展性以支持新的文件格式和操作系统。
初始的设计方案如下:
这种设计方式存在两个问题:
- 使用多层继承结构,使得系统中类的个数过多(如果要新增一种图片格式,至少要新增四个类,代码过于冗余)
- 系统扩展麻烦:每一个实体类既包含文件格式信息也包含操作系统信息,两种信息耦合度很高,导致不管是增加文件格式还是操作系统,系统都需要增加大量的实体类。
如何解决这种场景下的这两个问题,就需要使用桥接模式。
毛笔和蜡笔
在此之前,举一个毛笔和蜡笔的例子。
假如我们需要3种型号12中颜色的画笔,那么我们需要36种蜡笔,但只需要3支毛笔和12种颜料。毛笔的使用更加灵活也更易扩展。
很明显,毛笔将笔的型号和颜色进行了解耦,二者是相互独立的,而蜡笔中二者的耦合度很高。
桥接模式也是用了这种思想。
改进方案
利用桥接模式对上述的解决方案进行改进,得到:
这种设计方案解决的问题有:
- 将图片格式和操作系统解耦,将这两个维度分离,各自独立变化,进而对二者设计独立的继承等级结构,符合单一职责原则
- 摒弃多重继承,而使用关联关系(Image与ImageImp之间的关联),符合合成复用原则。
- 使用抽象类,符合里氏代换原则。
- 符合开闭原则。
- 使用抽象类,利用运行时多态,可以对子类做统一处理。
桥接模式
桥接模式:
将抽象部分和实现部分分离,使他们都可以独立的变化。
(通常情况下,我们将 具有两个变化维度的类的业务方法 和 与之关系最密切的维度 设计为 抽象类层次结构(抽象部分),而将另一个维度设计为 实现类层次结构(实现部分)
两个要点:
- 用 抽象关联(抽象类之间的关联关系) 取代 多继承
- 将类之间的 静态继承关系 转换为 动态的对象组合关系
设计结构图
其中:
- Abstraction 抽象类:定义一个Implementor类型的变量,实现与Implementor的抽象关联。抽象类中既可以包含抽象业务方法(abstract方法),也可以包含具体业务方法
- RefinedAbstraction(抽象类实体):实现了在Abstraction中的抽象方法,以及可以利用 Implementor变量调用Implementor中定义的业务方法
- Implementor 实现类接口:相当于实现部分的抽象类
- ConsreteImplementor 实现类实体:程序运行时,将替换父类,将自己的业务方法传递给抽象类实体
总结
桥接模式将实体的抽象部分和实现部分分离,使其独立变化。
满足:
- 单一职责原则
- 开闭原则
- 合成复用原则
- 里氏代换原则
总结
桥接模式将实体的抽象部分和实现部分分离,使其独立变化。
满足:
- 单一职责原则
- 开闭原则
- 合成复用原则
- 里氏代换原则
- 依赖倒转原则