桥接模式也称为桥梁模式,是结构型设计模式之一。桥接模式中体现了“单一职责原则”、“开闭原则”、“里氏替换原则”、“依赖倒置原则”等。同时它也是很实用的一种模式。
将抽象部分与现实部分分离,使它们都可以独立地进行变化。
(1)如果一个系统需要在构建的抽象化角色和具体角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系。
(2)对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,也可以考虑使用桥接模式。
(3)一个类存在两个独立变化的维度,且这两个维度都需要扩展。
(1)Abstraction
:抽象部分,该类保持一个对实现部分对象的引用,抽象部分中的方法需要调用实现部分的对象来实现,该类一般为抽象类。
(2)RefinedAbstraction
:优化抽象部分,抽象部分的具体实现,该类一般是对抽象部分的方法进行完善和扩展。
(3)Implementor
:实现部分。可以为接口或抽象类,其方法不一定要与抽象部分中的一致,一般情况下是由现实部分提供基本操作,而抽象部分定义的则是基于实现部分这些基本操作的业务方法。
(4)ConcreteImplementorA
、ConcreteImplementorB
:实现部分的具体实现。完善实现部分中的方法定义的具体逻辑。
以去咖啡店喝咖啡为例,我们假定咖啡有大杯加糖、大杯不加糖、小杯加糖和小杯不加糖四种。
给咖啡添加东西的抽象类:(Implementor)
public abstract class CoffeeAdditives {
/** * 具体要往咖啡里添加什么东西 * * @param 具体添加的东西 */
public abstract String addSomething();
}
加糖类实现:(ConcreteImplementorA)
public class Sugar extends CoffeeAdditives{
@Override
public String addSomething() {
return "加糖";
}
}
原味类实现:(ConcreteImplementorB)
public class Ordinary extends CoffeeAdditives{
@Override
public String addSomething() {
return "原味";
}
}
咖啡类:(Abstraction)
public abstract class Coffee{
protected CoffeeAdditives impl;
public Coffee(CoffeeAdditives impl) {
this.impl = impl;
}
/** * 咖啡具体什么样由子类决定 */
public abstract void makeCoffee();
}
大杯咖啡:(RefinedAbstraction)
public class LargeCoffee extends Coffee{
public LargeCoffee(CoffeeAdditives impl) {
super(impl);
}
@Override
public void makeCoffee() {
System.out.println("大杯的" + impl.addSomething() + "咖啡");
}
}
小杯咖啡:
public class SmallCoffee extends Coffee{
public SmallCoffee(CoffeeAdditives impl) {
super(impl);
}
@Override
public void makeCoffee() {
System.out.println("小杯的" + impl.addSomething() + "咖啡");
}
}
调用:
public class Client {
public static void main(String[] args) {
//原味
Ordinary implOrdinary = new Ordinary();
//加糖
Sugar implSugar = new Sugar();
//大杯咖啡 原味
LargeCoffee largeCoffeeOrdinary = new LargeCoffee(implOrdinary);
largeCoffeeOrdinary.makeCoffee();
//小杯咖啡 原味
SmallCoffee smallCoffeeOrdinary = new SmallCoffee(implOrdinary);
smallCoffeeOrdinary.makeCoffee();
//大杯咖啡 加糖
LargeCoffee largeCoffeeSugar = new LargeCoffee(implSugar);
largeCoffeeSugar.makeCoffee();
//小杯咖啡 加糖
SmallCoffee smallCoffeeSugar = new SmallCoffee(implSugar);
smallCoffeeSugar.makeCoffee();
}
}
结果:
大杯的原味咖啡
小杯的原味咖啡
大杯的加糖咖啡
小杯的加糖咖啡
主要代码如下:
public abstract class Window {
//部分省略
/** * Set the window manager for use by this Window to, for example, * display panels. This is <em>not</em> used for displaying the * Window itself -- that must be done by the client. * * @param wm The window manager for adding new windows. */
public void setWindowManager(WindowManager wm, IBinder appToken, String appName) {
setWindowManager(wm, appToken, appName, false);
}
/** * Set the window manager for use by this Window to, for example, * display panels. This is <em>not</em> used for displaying the * Window itself -- that must be done by the client. * * @param wm The window manager for adding new windows. */
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
mAppToken = appToken;
mAppName = appName;
mHardwareAccelerated = hardwareAccelerated
|| SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
//*将Window与WindowManager绑定
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
//部分省略
}
(1)分离抽象与现实、灵活的扩展以及对客户来说透明的实现。
(2)桥接模式可以取代多层继承,大大减少了子类的个数。
不容易设计,对开发者来说要有一定的经验要求。理解很容易,设计却不容易。