桥接模式 详解
定义
将抽象部分与它的实现部分分离,是它们都可以独立地变化;
结构型模式
角色
- 抽象化角色(Abstaction):定义抽象接口,拥有一个Implementor类型对象引用;
- 重定义抽象化角色(RefinedAbstraction):扩展Abstraction中的接口定义;
- 实现化角色(Implementor): 实现化的接口;
- 具体实现化角色(ConcreteImplementor): 实现实现化的接口;
从网上找到的例图
适用场景
- 如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的联系;
- 设计要求实现化角色的任何改变不应当影响客户端,或者说实现化角色的改变对客户端是完全透明的;
- 一个构件有多于一个的抽象化角色和实现化化角色,系统需要它们之间进行动态耦合;
- 虽然在系统中使用继承是没问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求独立管理这两者;
例子
实现代码
/**
* Created by George on 16/7/5.
*/
// 抽象化角色
var AbstractRoad = function () {
this.car = null;
this.setCar = function (car) {
this.car = car;
};
this.run = function () {
console.log("在路上");
};
};
// 具体化角色
var SpeedRoad = function () {};
SpeedRoad.prototype = new AbstractRoad();
SpeedRoad.prototype.run = function () {
this.car.run();
console.log("在高速公路");
};
var StreetRoad = function () {};
StreetRoad.prototype = new AbstractRoad();
StreetRoad.prototype.run = function () {
this.car.run();
console.log("在街道");
};
// 抽象化实现
var AbstractCar = function () {
this.run = function () {
console.log("车");
};
};
// 具体化实现
var Car = function () {};
Car.prototype = new AbstractCar();
Car.prototype.run = function () {
console.log("汽车");
};
var Bus = function () {};
Bus.prototype = new AbstractCar();
Bus.prototype.run = function () {
console.log("公交车");
};
//主函数
var speedRoad = new SpeedRoad();
var car = new Car();
speedRoad.setCar(car);
speedRoad.run();
console.log("----------------");
var streetRoad = new StreetRoad();
var bus = new Bus();
streetRoad.setCar(bus);
streetRoad.run();
实现结果:
优缺点
- 桥接模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化;
- 所谓抽象和实现沿着各自维度的变化;
- 类似于多继承方案,但是多继承方案往往违背了类的单一职责原则(一个类只有一个变化),复用性比较差;
注意的是
- 装饰者模式是把子类中比基类多出来的部分放到单独的类里面,以适应新功能增加的需要,当我们把描述新功能的类封装到基类的对象里面时,就得到了所需要的子类对象,这些描述新功能的类通过组合可以实现很多的功能组合;
而桥接模式则把原来的基类的实现化细节抽象出来,再构造到一个实现化的结构中,然后再把原来的基类改造成一个抽象化的等级结构,这样就可以实现系统在多个维度上的独立变化;
![](https://i.loli.net/2018/11/17/5beff4d639cbb.jpg)
关注公众号:数据结构与算法那些事儿,每天一篇数据结构与算法