在现实生活中,某些类具有两个或多个维度的变化,如图形既可按形状分,又可按颜色分。如何设计类似于 Photoshop 这样的软件,能画不同形状和不同颜色的图形呢?如果用继承方式,m 种形状和 n 种颜色的图形就有 m×n 种,不但对应的子类很多,而且扩展困难。
当然,这样的例子还有很多,如不同颜色和字体的文字、不同品牌和功率的汽车、不同性别和职业的男女、支持不同平台和不同文件格式的媒体播放器等。如果用桥接模式就能很好地解决这些问题。
桥接模式的定义与特点
桥接(Bridge)模式的定义如下:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
通过上面的讲解,我们能很好的感觉到桥接模式遵循了里氏替换原则和依赖倒置原则,最终实现了开闭原则,对修改关闭,对扩展开放。这里将桥接模式的优缺点总结如下。
桥接(Bridge)模式的优点是:
- 抽象与实现分离,扩展能力强
- 符合开闭原则
- 符合合成复用原则
- 其实现细节对客户透明
缺点是:由于聚合关系建立在抽象层,要求开发者针对抽象化进行设计与编程,能正确地识别出系统中两个独立变化的维度,这增加了系统的理解与设计难度。
桥接模式的结构与实现
可以将抽象化部分与实现化部分分开,取消二者的继承关系,改用组合关系。
1. 模式的结构
桥接(Bridge)模式包含以下主要角色。
- 抽象化(Abstraction)角色:定义抽象类,并包含一个对实现化对象的引用。
- 扩展抽象化(Refined Abstraction)角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
- 实现化(Implementor)角色:定义实现化角色的接口,供扩展抽象化角色调用。
- 具体实现化(Concrete Implementor)角色:给出实现化角色接口的具体实现。
其结构图如图 1 所示。
class BridgeTest { public static void main(String[] args) { Implementor imple = new ConcreteImplementorA(); Abstraction abs = new RefinedAbstraction(imple); abs.Operation(); } //实现化角色 interface Implementor { public void OperationImpl(); } //具体实现化角色 static class ConcreteImplementorA implements Implementor{ @Override public void OperationImpl() { System.out.println("具体实现化(Concrete Implementor)角色被访问"); } } //抽象化角色 static abstract class Abstraction { protected Implementor imple; protected Abstraction(Implementor imple) { this.imple = imple; } public abstract void Operation(); } //扩展抽象化角色 static class RefinedAbstraction extends Abstraction{ protected RefinedAbstraction(Implementor imple) { super(imple); } @Override public void Operation() { System.out.println("扩展抽象化(Refined Abstraction)角色被访问"); imple.OperationImpl(); } } }
桥接模式的应用实例
【例1】用桥接(Bridge)模式模拟女士皮包的选购。
分析:女士皮包有很多种,可以按用途分、按皮质分、按品牌分、按颜色分、按大小分等,存在多个维度的变化,所以采用桥接模式来实现女士皮包的选购比较合适。
class BagManage { public static void main(String[] args) { Color color = new Red(); Bag bag = new HandBag(); bag.setColor(color); String name = bag.getName(); System.out.println(name); } //实现化角色:颜色 interface Color { String getColor(); } //具体实现化角色:黄色 static class Yellow implements Color { public String getColor() { return "yellow"; } } //具体实现化角色:红色 static class Red implements Color { public String getColor() { return "red"; } } //抽象化角色:包 static abstract class Bag { protected Color color; public void setColor(Color color) { this.color = color; } public abstract String getName(); } //扩展抽象化角色:挎包 static class HandBag extends Bag{ @Override public String getName() { return color.getColor() + "HandBag"; } } //扩展抽象化角色:钱包 static class Wallet extends Bag { public String getName() { return color.getColor() + "Wallet"; } } } class ReadXMl{ public static Object getObject(String args) { try { DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = dFactory.newDocumentBuilder(); Document doc; doc = builder.parse(new File("E:\3-1Q115130045\config.xml")); NodeList nl = doc.getElementsByTagName("className"); Node classNode = null; if (args.equals("color")) { classNode = nl.item(0).getFirstChild(); } else if (args.equals("bag")) { classNode = nl.item(1).getFirstChild(); } String cName = "bridge." + classNode.getNodeValue(); Class<?> c = Class.forName(cName); Object obj = c.newInstance(); return obj; } catch (Exception e) { e.printStackTrace(); return null; } } }