设计模式初探-桥接(Bridge)模式
桥接(Bridge)模式,又称Handle/Body模式,属于对象结构型模式。用于将抽象部分与它的实现部分分离,使它们都可以独立地变化。比如常见的电脑窗口界面,不同的操作系统其窗口界面绘制的原理肯定不一样。这里,窗口界面就相当于抽象部分(Abstraction),而窗口界面本身也可以随着功能的不同而进行扩充,扩充的窗口就是抽象窗口的扩充抽象类(RefinedAbstraction),这些抽象需要具体的操作系统实现才能被我们看到,那基于操作系统的窗口实现就是实现部分(Implementor),不管是Window,Linux还是Mac。Window,Linux或Mac则是实现接口的具体实现类(ConcreteImplementor)。
一、使用场景
1、如果一个系统需要在抽象和具体之间增加更多的灵活性,避免在两个层次之间建立静态的继承关系,那么可以通过桥接模式使它们在抽象层之上建立一个关联关系,从而增加灵活性。
2、“抽象部分”和“实现部分”可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。
3、一个类存在两个(或多个)独立变化的维度,且这两个(或多个)维度都需要独立进行扩展。
4、对于那些不希望使用继承或因为多层继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
二、UML图
三、Java实现
package study.patterns.bridge; /** * 桥接模式:通过将维度解耦来处理多维度的变化。 * @author qbg */ public class BridgePattern { public static void main(String[] args) { /** * 对于客户端而言,可以针对两个维度的抽象层编程,在程序运行时再动态确定两个维度的子类, * 动态组合对象,将两个独立变化的维度完全解耦,以便能够灵活地扩充任一维度而对另一维度不造成任何影响。 */ Brush brush = new LargeImpl(); BrushImpl impl = new RedImpl(); brush.setBrushImpl(impl); brush.drawPicture("蒙娜丽莎的微笑"); } } /** * 辅助类:画 */ class Picture{} /** * 画笔的抽象基类:变化维度有种类,型号,颜色等, * 此处拿型号(大,中,小)和颜色(红,绿,蓝)做示例维度. * 型号为抽象维度,颜色为实现维度. * 如果需要添加新型号的画笔,只需扩充抽象类Brush; * 如果需要添加新的画笔颜色,只需增加BrushImpl接口的具体实现类. */ abstract class Brush{ protected BrushImpl impl; public void setBrushImpl(BrushImpl impl){ this.impl = impl; } /** * 抽象部分的业务方法:画画 */ public abstract void drawPicture(String name); } /** * 抽象画笔颜色实现类:实现类接口 */ interface BrushImpl{ public void doDraw(Picture pic); //涂抹相应的颜色 } /** * 红色画笔实现类:具体实现类 */ class RedImpl implements BrushImpl{ @Override public void doDraw(Picture pic) { System.out.println("涂抹红色。。。。"); } } /** * 绿色画笔实现类:具体实现类 */ class GreenImpl implements BrushImpl{ @Override public void doDraw(Picture pic) { System.out.println("涂抹绿色 。。。。"); } } /** * 蓝色画笔实现类: 具体实现类 */ class BlueImpl implements BrushImpl{ @Override public void doDraw(Picture pic) { System.out.println("涂抹蓝色 。。。。"); } } /** * 大号画笔:扩充抽象类 */ class LargeImpl extends Brush{ @Override public void drawPicture(String name) { //模拟使用画笔勾勒画的线条 Picture pic = new Picture(); impl.doDraw(pic); System.out.println(name+",使用大号画笔绘制。。。"); } } /** * 中号画笔:扩充抽象类 */ class MediumImpl extends Brush{ @Override public void drawPicture(String name) { //模拟使用画笔勾勒画的线条 Picture pic = new Picture(); impl.doDraw(pic); System.out.println(name+",使用中号画笔绘制。。。"); } } /** * 小号画笔:扩充抽象类 */ class TinyImpl extends Brush{ @Override public void drawPicture(String name) { //模拟使用画笔勾勒画的线条 Picture pic = new Picture(); impl.doDraw(pic); System.out.println(name+",使用小号画笔绘制。。。"); } }
四、模式优缺点
优点:
1、分离抽象接口及其实现部分。桥接模式使用“对象间的关联关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。所谓抽象和实现沿着各自维度的变化,也就是说抽象和实现不再在同一个继承层次结构中,而是“子类化”它们,使它们各自都具有自己的子类,以便任何组合子类,从而获得多维度组合对象。
2、在很多情况下,桥接模式可以取代多层继承方案,多层继承方案违背了“单一职责原则”,复用性较差,且类的个数非常多,桥接模式是比多层继承方案更好的解决方法,它极大减少了子类的个数。
3、桥接模式提高了系统的可扩展性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统,符合“开闭原则”。
缺点:
1、桥接模式的使用会增加系统的理解与设计难度,由于关联关系建立在抽象层,要求开发者一开始就针对抽象层进行设计与编程。
2、桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性,如何正确识别两个独立维度也需要一定的经验积累。
PS:上面的总结参考自livelion,经验尚浅,只能仰仗大神!