我们是不是遇到过,在一款手机上的应用在另外一种牌子的手机上会出现安装失败。像手机自带的app如通讯率、小游戏等。如何解决这样的问题呢?使用继承?嗯,是个不错的办法,但是现在增加一个app如音乐播放器。显然这会带来系统变得庞大、复杂。
其实这就是我们在学习继承时所带来的诟病。我们学会使用继承后,见识到它既新颖又功能强大,所以只要能用,我们都用上继承。这就好比有了‘新锤子’,所有的东西都像钉子。但事实上,用继承会带来很多不必要的麻烦。这是由于继承的性质决定的,对象的关系是在编译时就定义好了,所以无法在运行时改变从父类继承的实现,子类的实现与它的父类有非常的依赖关系,以至于父类实现的任何变化将带来子类的不必要的变化。当你需要需要复用子类时,如果继承下来的实现不适用现在的问题。那末就需要改变父类或者被其他更合适的类替换。显然这有悖开放封闭原则。
注意:我们应该在明确类之间的关系是IS-A时才能用继承。
模式定义
桥接模式即将抽象部分与它的实现部分分离开来,使他们都可以独立变化。
桥接模式将继承关系转化成关联关系,它降低了类与类之间的耦合度,减少了系统中类的数量,也减少了代码量。
将抽象部分与他的实现部分分离这句话不是很好理解,其实这并不是将抽象类与他的派生类分离,而是抽象类和它的派生类用来实现自己的对象。这样还是不能理解的话。我们就先来认清什么是抽象化,什么是实现化,什么是脱耦。
抽象化:其概念是将复杂物体的一个或几个特性抽出去而只注意其他特性的行动或过程。在面向对象就是将对象共同的性质抽取出去而形成类的过程。
实现化:针对抽象化给出的具体实现。它和抽象化是一个互逆的过程,实现化是对抽象化事物的进一步具体化。
脱耦:脱耦就是将抽象化和实现化之间的耦合解脱开,或者说是将它们之间的强关联改换成弱关联,将两个角色之间的继承关系改为关联关系。
对于那句话:将抽象部分与他的实现部分分离套用《大话设计模式》里面的就是实现系统可能有多个角度分类,每一种角度都可能变化,那么把这种多角度分类给分离出来让他们独立变化,减少他们之间耦合。
桥接模式中的所谓脱耦,就是指在一个软件系统的抽象化和实现化之间使用关联关系(组合或者聚合关系)而不是继承关系,从而使两者可以相对独立地变化,这就是桥接模式的用意。
模式结构
模式实现
手机软件
package com.nchu.bridge;
abstract class HandsetSoft {
public abstract void run();
}
手机游戏
package com.nchu.bridge;
public class HandsetGame extends HandsetSoft {
@Override
public void run() {
System.out.println("运行手机游戏!");
}
}
手机通讯录
package com.nchu.bridge;
public class HandsetAddressList extends HandsetSoft {
@Override
public void run() {
System.out.println("运行手机通讯录!");
}
}
手机品牌类
package com.nchu.bridge;
abstract class HandsetBrand {
protected HandsetSoft handsetSoft = null;
public void setHandsetSoft(HandsetSoft soft){
handsetSoft = soft;
}
public abstract void run();
}
手机品牌A
package com.nchu.bridge;
public class HandsetBrandA extends HandsetBrand {
@Override
public void run() {
handsetSoft.run();
}
}
手机品牌B
package com.nchu.bridge;
public class HandsetBrandB extends HandsetBrand {
@Override
public void run() {
handsetSoft.run();
}
}
测试类
package com.nchu.bridge;
public class Client {
public static void main(String[] args) {
HandsetBrand ab = new HandsetBrandA();
ab.setHandsetSoft(new HandsetGame());
ab.run();
ab.setHandsetSoft(new HandsetAddressList());
ab.run();
ab = new HandsetBrandB();
ab.setHandsetSoft(new HandsetGame());
ab.run();
ab.setHandsetSoft(new HandsetAddressList());
ab.run();
}
}
使用场景
1、如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
2、对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
3、一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
模式优缺点
优点
1、分离抽象接口及其实现部分。提高了比继承更好的解决方案。
2、桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统。
3、实现细节对客户透明,可以对用户隐藏实现细节。
缺点
2、桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性。
模式总结
1、桥接模式实现了抽象化与实现化的脱耦。他们两个互相独立,不会影响到对方。