前言
桥接模式也称为桥梁模式,属于结构型设计模式。名如其名,桥梁模式就是连接没有关系的两个地,起到连接两边的作用,换点技术性语言,桥接模式就是将抽象部分和实现部分分离,使它们都可以独立进行变化,这个桥梁也就是连接抽象和实现部分了。
适用
任何多维变化类,亦或是多个树状类之间的耦合都可以用桥接模式来解耦。
UML角色
ABStraction:抽象部分,该类保持一个对实现部分的引用,抽象部分中的方法需要调用实现部分的对象来实现,该类一般为抽象类。
RefinedAbstraction:扩展抽象类,抽象部分的具体实现,该类一般是对抽象部分的方法进行完善和扩展。
Implementor:实现类接口(抽象类),其方法不一定要和抽象部分一致,一般由实现类提供基本操作,而抽象部分定义的则是基于这些基本操作的业务方法。
ConcreteImplementor:具体实现类,实现部分的具体逻辑。
Demo
抽象出来一个简单的demo:汽车行驶在路上,车分为N多种,咱只抽象出奔驰、宝马、二手奥拓,路分为很多种,咱简单抽象出高速和乡道,这是两个没关系的两个部分,咱用桥给连接起来,首先咱们先吧路实现了,抽象类AbsRoad 以及实现类的两种路的类:
package com.demo.bridge;
/**
* Created by italkbb on 2018/1/22.
*/
public abstract class AbsRoad {
protected AbsCar car;
public AbsCar getCar() {
return car;
}
public void setCar(AbsCar car) {
this.car = car;
}
/**
* 抽象公用方法
* 行驶方法
*/
public abstract void travel();
}
package com.demo.bridge;
/**
* Created by italkbb on 2018/1/22.
* 高速公路
*/
public class HSpeedRoad extends AbsRoad {
@Override
public void travel() {
car.travel();
System.out.println("高速公路");
}
}
package com.demo.bridge;
/**
* Created by italkbb on 2018/1/22.
*/
public class TownshipRoad extends AbsRoad {
@Override
public void travel() {
car.travel();
System.out.println("乡间小道");
}
}
下面是实现部分,我们的另一端是汽车,先抽象出一个汽车类,然后实现三种汽车:
package com.demo.bridge;
/**
* Created by italkbb on 2018/1/22.
*/
public abstract class AbsCar {
public abstract void travel();
}
package com.demo.bridge;
/**
* Created by italkbb on 2018/1/22.
*/
public class BenzCar extends AbsCar {
@Override
public void travel() {
System.out.print("奔驰车行驶在");
}
}
package com.demo.bridge;
/**
* Created by italkbb on 2018/1/22.
*/
public class BMWCar extends AbsCar {
@Override
public void travel() {
System.out.print("宝马车行驶在");
}
}
package com.demo.bridge;
/**
* Created by italkbb on 2018/1/22.
*/
public class SecondHandAltoCar extends AbsCar {
@Override
public void travel() {
System.out.print("二手奥拓车行驶在");
}
}
两部分都实现了,我们可以调用一下:
/**
* demo测试代码
*/
private void initDemo() {
// 奔驰车上高速
AbsRoad road = new HSpeedRoad();
road.setCar(new BenzCar());
road.travel();
// 二手奥拓上高速
road.setCar(new SecondHandAltoCar());
road.travel();
// 奔驰车开个小道
road = new TownshipRoad();
road.setCar(new BenzCar());
road.travel();
// 宝马上个小道
road.setCar(new BMWCar());
road.travel();
}
很简单的demo,我们看一下ide效果吧:
01-22 17:53:14.941 7287-7287/teltplay.example.com.kotlindemo I/System.out: 奔驰车行驶在高速公路
01-22 17:53:14.942 7287-7287/teltplay.example.com.kotlindemo I/System.out: 二手奥拓车行驶在高速公路
01-22 17:53:14.942 7287-7287/teltplay.example.com.kotlindemo I/System.out: 奔驰车行驶在乡间小道
01-22 17:53:14.942 7287-7287/teltplay.example.com.kotlindemo I/System.out: 宝马车行驶在乡间小道
再扩充一下,如果我们需要增加一个维度,比如增加一个驾驶人在这个demo中,也很简单,我们抽象出一个Driver:
package com.demo.bridge;
/**
* Created by italkbb on 2018/1/22.
*/
public abstract class Driver {
private AbsRoad road;
public AbsRoad getRoad() {
return road;
}
public void setRoad(AbsRoad road) {
this.road = road;
}
public abstract void travel();
}
我们实现一个驾驶人张师傅:
package com.demo.bridge;
/**
* Created by italkbb on 2018/1/22.
*/
public class ZhangDriver extends Driver {
@Override
public void travel() {
System.out.print("张师傅开");
road.travel();
}
}
调用只需要在之前的代码后加上Drvier类:
/**
* demo测试代码
*/
private void initDemo() {
// 奔驰车上高速
AbsRoad road = new HSpeedRoad();
road.setCar(new BenzCar());
road.travel();
// 二手奥拓上高速
road.setCar(new SecondHandAltoCar());
road.travel();
// 奔驰车开个小道
road = new TownshipRoad();
road.setCar(new BenzCar());
road.travel();
// 宝马上个小道
road.setCar(new BMWCar());
road.travel();
// 张师傅开车
Driver driver = new ZhangDriver();
driver.setRoad(road);
driver.travel();
}
这次的打印结果大家可以估计:
01-22 18:05:54.651 9905-9905/teltplay.example.com.kotlindemo I/System.out: 奔驰车行驶在高速公路
01-22 18:05:54.651 9905-9905/teltplay.example.com.kotlindemo I/System.out: 二手奥拓车行驶在高速公路
01-22 18:05:54.651 9905-9905/teltplay.example.com.kotlindemo I/System.out: 奔驰车行驶在乡间小道
01-22 18:05:54.651 9905-9905/teltplay.example.com.kotlindemo I/System.out: 宝马车行驶在乡间小道
01-22 18:05:54.652 9905-9905/teltplay.example.com.kotlindemo I/System.out: 张师傅开宝马车行驶在乡间小道
后记
说点优点:分离抽象接口及其实现部分。提高了比继承更好的解决方案;桥接模式提高了系统的可扩充性,增加维度变得很容易;实现细节对客户透明,可以对用户隐藏实现细节。缺点:桥接模式的引入会增加系统的理解与设计难度,由于聚合关联建立在抽象层,要求开发者针对抽象进行设计与编程;其次需要正确识别出系统中两个独立变化的维度,有一定的局限性。