1 概述
1.1 引入
现在有一个需求,需要创建不同的图形,并且每个图形都有可能会有不同的颜色。我们可以利用继承的方式来设计类的关系:
我们可以发现有很多的类,假如我们再增加一个形状或再增加一种颜色,就需要创建更多的类。
试想,在一个有多种可能会变化的维度的系统中,用继承方式会造成类爆炸,扩展起来不灵活。每次在一个维度上新增一个具体实现都要增加多个子类。为了更加灵活的设计系统,我们此时可以考虑使用桥接模式。
1.2 定义
定义:
将抽象与实现分离
,使它们可以独立变化
。它是用组合关系代替继承关系
来实现,从而降低了抽象和实现这两个可变维度的耦合度。
桥接(Bridge)模式包含以下主要角色:
- 抽象化(Abstraction)角色 :定义抽象类,并包含一个对实现化对象的引用。
- 扩展抽象化(Refined Abstraction)角色 :是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
- 实现化(Implementor)角色 :定义实现化角色的接口,供扩展抽象化角色调用。
- 具体实现化(Concrete Implementor)角色 :给出实现化角色接口的具体实现。
2 案例
女士皮包有很多种,可以按用途分、按皮质分、按品牌分、按颜色分、按大小分等,存在多个维度的变化,所以采用桥接模式来实现女士皮包的选购比较合适。
本实例按用途分可选钱包(Wallet)和挎包(HandBag),按颜色分可选黄色(Yellow)和红色(Red)。可以按两个维度定义为颜色类和包类。
颜色类(Color)是一个维度,定义为实现化角色,它有两个具体实现化角色:黄色和红色,通过 getColor() 方法可以选择颜色;包类(Bag)是另一个维度,定义为抽象化角色,它有两个扩展抽象化角色:挎包和钱包,它包含了颜色类对象,通过 getName() 方法可以选择相关颜色的挎包和钱包。
- Color
package study.wyy.design.bridge;
/**
* @author 20116651
* @description
* @date 2021/1/4 9:33
*/
public interface Color {
String getColor();
}
- Color实现类
package study.wyy.design.bridge;
/**
* @author 20116651
* @description
* @date 2021/1/4 9:35
*/
public class Red implements Color{
@Override
public String getColor() {
return "Red";
}
}
package study.wyy.design.bridge;
/**
* @author 20116651
* @description
* @date 2021/1/4 9:34
*/
public class Yellow implements Color{
@Override
public String getColor() {
return "Yellow";
}
}
- 包
package study.wyy.design.bridge;
/**
* @author 20116651
* @description
* @date 2021/1/4 9:37
*/
public abstract class Bag {
private Color color;
public void setColor(Color color) {
this.color = color;
}
abstract String getType();
}
package study.wyy.design.bridge;
/**
* @author 20116651
* @description
* @date 2021/1/4 9:39
*/
public class HandBag extends Bag{
@Override
String getType() {
return "挎包";
}
}
package study.wyy.design.bridge;
/**
* @author 20116651
* @description
* @date 2021/1/4 9:39
*/
public class Wallet extends Bag{
@Override
String getType() {
return "钱包";
}
}
- 测试
package study.wyy.design.bridge;
/**
* @author 20116651
* @description
* @date 2021/1/4 9:44
*/
public class Client {
public static void main(String[] args) {
Bag bag =new HandBag();
bag.setColor(new Yellow());
}
}
3 应用场景
当一个类内部具备两种或多种变化维度时,使用桥接模式可以解耦这些变化的维度,使高层代码架构稳定。
桥接模式通常适用于以下场景。
- 当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时。
- 当一个系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时。
- 当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时。
桥接模式的一个常见使用场景就是替换继承。我们知道,继承拥有很多优点,比如,抽象、封装、多态等,父类封装共性,子类实现特性。继承可以很好的实现代码复用(封装)的功能,但这也是继承的一大缺点。
因为父类拥有的方法,子类也会继承得到,无论子类需不需要,这说明继承具备强侵入性(父类代码侵入子类),同时会导致子类臃肿。因此,在设计模式中,有一个原则为优先使用组合/聚合,而不是继承。