顿搜
桥接模式(Bridge)——23种设计模式之结构型模式
在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度?
要做到“抽象(接口)与实现分离”,最常用的办法是 定义一个抽象类,然后在子类中提供实现。也就是说, 用继承机制达到“抽象(接口)与实现分离但是这种方法不够灵活,继承机制把实现与抽象部分 永久地绑定起来,要想独立地修改、扩展、重用抽象 (接口)与实现都非常困难。 一种可变性不应该散落在代码的很多角落里, 而应被封装在一个对象里。继承可看作封装变 化的方法。 一种可变性不应与另一种可变性混在一起。继承层次不应太多。
要尽量使用组合/聚合,尽量不要使用继承。在一个新的对象里面使用一些已有的对象, 使之成为新对象的一部分,新对象通过向这 些对象的委派达到复用已有功能的目的。
桥接模式是“对变化的封装”原则以及合成/聚合复 用原则的极好例子。分离接口及其实现部分。抽象类的实现可以在运 行时刻进行配置,一个对象甚至可以在运行时刻 改变它的实现
一、抽象与具体
抽象和具体相关补充:
- ①、抽象化与实现化的最简单实现,也就是“开-闭”原则在 类层次上的最简单实现。
- ②、 一般来说,一个继承结构中的第一层是抽象角色,封装 了抽象的商业逻辑,这是系统中不变的部分;第二层是 实现角色,封装了设计中会变化的因素。这个实现允许实现化角色有多态性变化。
- ③、客户端可以持有抽象化类型的对象,而不在意对象的真实类型是“实现化”。
- ④、每个继承关系都封装了一个变化的因素,而一个继承关系不应当同时处理两个变化因素
- ⑤、两个变化因素应当彼此独立,可以在不影响另一者的情况下独立演化。
- ⑥、使用两个独立的等级结构封装两个独立的变化因素,它们之间使用聚合关系,达到功能复合的目的。
- ⑦、依赖倒置原则:抽象不应该依赖于实现细节,实现细节应该依赖于抽象。
二、类图表示
桥接模式涉及到Abstraction()
- ①、Abstraction:定义抽象类的接口,维护一个指向Implementor类型对象的指针
- ②、RefinedAbstraction:扩充由Abstraction定义的接口
- ③、Implementor:定义实现类的接口,不一定要与Abstraction的接口完全一致,甚至可以完全不同
- ④、ConcreteImplementor:实现Implementor接口并定义它的具体实现
三、代码示例
//定义抽象类的接口
public abstract class Clothing {
public abstract void dressCloth(Person person);
}public class Jacket extends Clothing {
@Override
public void dressCloth(Person person) {
System.out.println(person.getType() + "穿上马甲!");
}
}public class Trouser extends Clothing {
@Override
public void dressCloth(Person person) {
System.out.println(person.getType() + "穿上裤子!");
}
}//定义实现类的接口
public abstract class Person {
private String type;
private Clothing clothing;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Clothing getClothing() {
return clothing;
}
public void setClothing(Clothing clothing) {
this.clothing = clothing;
}
//抽象方法
public abstract void dress();
}public class Man extends Person {
public Man(){
setType("男人");
}
@Override
public void dress() {
getClothing().dressCloth(this);
}
}public class Woman extends Person {
public Woman(){
setType("女人");
}
@Override
public void dress() {
getClothing().dressCloth(this);
}
}public class ClientTest {
public static void main(String[] args) {
//两类人
Person man = new Man();
Person lady = new Woman();
//两种衣服的类
Clothing jacket = new Jacket();
Clothing trouser = new Trouser();
jacket.dressCloth(man);
trouser.dressCloth(man);
jacket.dressCloth(lady);
trouser.dressCloth(lady);
}
}四、优缺点分析
1、优点
- ①、使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使抽象和实现可以沿着各自的维度变化
- ②、Bridge模式有时类似于多继承,但多继承往往违背单一职责原则,复用性较差。 Bridge模式较之更优。
- ③、抽象与实现两部分可以单独扩充,实现细节对客户透明
- ④、抽象类的实现可以在运 行时刻进行配臵,一个对象甚至可以在运行时刻改变它的实现
五、与其他模式比较
1、与抽象工厂模式比较:
- ①、Abstract Factory可以用来创建和配置Bridge模式
2、与适配器模式比较
- ①、Adapter模式用来帮助无关的类协同工作,通 常在系统设计完成后才会被使用
- ②、Bridge模式则在系统开始时就被使用,它使得 抽象接口和实现部分可以独立进行改变
六、适用场景
适用场景:
- ①、系统需要在构件的抽象化角色和具体化角色间增加更多的灵活性,避免在两个层次之间建立静态的联系。
- ②、设计要求实现化角色的任何改变不应当影响客户端, 或者说实现化角色的改变对客户端是完全透明的。
- ③、一个构件有多于一个的抽象化角色和实现化角色,系统需要它们之间进行动态耦合。
- ④、虽然在系统中使用继承没问题,但抽象化角色和具体化角色需独立变化,设计要求需要独立管理这两者。
七、总结
桥接模式是“对变化的封装”原则以及合成/聚合复 用原则的极好例子。
- ①、一个好的设计通常没有多于两层的继承等级结构。如 果出现两个以上的变化因素,就需要找出哪一个因素 是静态的,可以使用继承关系;哪一个是动态的,必 须使用聚合关系。
- ②、Bridge模式的应用一般在“两个非常强的变化维 度”,有时应用中即使有两个变化的纬度,但在某 个方向的变化纬度并不剧烈----即两个变化不会导致纵横交错的结果,并不一定要使用Bridge模式。
