JAVA设计模式之桥接模式
概念:
在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度?这就要使用Bridge模式。
意图:
将抽象部分与实现部分分离,使它们都可以独立的变化。
——《设计模式》GOF
桥接模式(bridge),处理多层继承结构,处理多维度变化的场景,将各个维度设计成独立的继承结构,使各个维度可以独立的扩展在抽象层建立关联。
由于一个对象有多个维度决定,导致多继承方式,而java不支持多继承,则需要使用多层继承,导致类关系复杂且庞大,新增维度变化会导致类的膨胀,而且违反单一职责原则,一个类,会有两个引起这个类变化的原因。
类图
应用:
JDBC驱动程序
AWT中的Peer架构
银行日志管理:
格式分类:操作日志,交易日志,异常日志
距离分类:本地记录日志,异地记录日志
人力资源系统中的奖金计算模块:
奖金分类:个人奖金,团体奖金,激励奖金
部门分类:人事部门,销售部门,研发部门
OA系统中的消息处理:
业务类型:普通消息,加急消息,特级消息
发送消息方式:系统内消息,手机短信,邮件
代码:
采用桥接模式之前:
//基类 路
class Road {
void run() {
System.out.println("路");
}
}
//市区街道
class Street extends Road {
void run() {
System.out.println("市区街道");
}
}
//高速公路
class SpeedWay extends Road {
void run() {
System.out.println("高速公路");
}
}
//小汽车在市区街道行驶
class CarOnStreet extends Street {
void run() {
System.out.println("小汽车在市区街道行驶");
}
}
//小汽车在高速公路行驶
class CarOnSpeedWay extends SpeedWay {
void run() {
System.out.println("小汽车在高速公路行驶");
}
}
//公交车在市区街道行驶
class BusOnStreet extends Street {
void run() {
System.out.println("公交车在市区街道行驶");
}
}
//公交车在高速公路行驶
class BusOnSpeedWay extends SpeedWay {
void run() {
System.out.println("公交车在高速公路行驶");
}
}
//测试
public static void main(String[] args) {
//小汽车在高速公路行驶
CarOnSpeedWay carOnSpeedWay = new CarOnSpeedWay();
carOnSpeedWay.run();
//公交车在市区街道行驶
BusOnStreet busOnStreet = new BusOnStreet();
busOnStreet.run();
}
采用桥接模式后:
abstract class AbstractRoad{
AbstractCar aCar;
void run(){};
}
abstract class AbstractCar{
void run(){};
}
class Street extends AbstractRoad{
@Override
void run() {
// TODO Auto-generated method stub
super.run();
aCar.run();
System.out.println("在市区街道行驶");
}
}
class SpeedWay extends AbstractRoad{
@Override
void run() {
// TODO Auto-generated method stub
super.run();
aCar.run();
System.out.println("在高速公路行驶");
}
}
class Car extends AbstractCar{
@Override
void run() {
// TODO Auto-generated method stub
super.run();
System.out.print("小汽车");
}
}
class Bus extends AbstractCar{
@Override
void run() {
// TODO Auto-generated method stub
super.run();
System.out.print("公交车");
}
}
public static void main(String[] args){
AbstractRoad speedWay = new SpeedWay();
speedWay.aCar = new Car();
speedWay.run();
AbstractRoad street = new Street();
street.aCar = new Bus();
street.run();
}
通过对象组合的方式,Bridge 模式把两个角色之间的继承关系改为了耦合的关系,从而使这两者可以从容自若的各自独立的变化,这也是Bridge模式的本意。
这样增加了客户程序与路与汽车的耦合。其实这样的担心是没有必要的,因为这种耦合性是由于对象的创建所带来的,完全可以用创建型模式去解决。在应用时结合创建型设计模式来处理具体的问题
总结
- Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。
- 所谓抽象和实现沿着各自维度的变化,即“子类化”它们,得到各个子类之后,便可以任意它们,从而获得不同路上的不同汽车。
- Bridge模式有时候类似于多继承方案,但是多继承方案往往违背了类的单一职责原则(即一个类只有一个变化的原因),复用性比较差。Bridge模式是比多继承方案更好的解决方法。
- Bridge模式的应用一般在“两个非常强的变化维度”,有时候即使有两个变化的维度,但是某个方向的变化维度并不剧烈——换言之两个变化不会导致纵横交错的结果,并不一定要使用Bridge模式。
桥接模式可以取代多层继承的方案。多层继承违背了单一职责原则,复用性差,类的个数非常多。桥接模式可以极大的减少子类的个数,从而降低管理和维护成本。
桥接模式极大的提高了系统的可扩展性,在两个变化维度中任意扩展一个维度,都不需要修改原有的系统,符合开闭原则。