目录
什么是桥接模式
桥接(Bridge)模式是用于把抽象化与实现化解耦,使得二者可以独立变化。把抽象(abstraction)与行为实现(implementation)分离开来,从而可以保持各部分的独立性以及应对它们的功能扩展。其归属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。
说⽩了核⼼实现也就是在A类中含有B类接口,通过构造函数传递B类的实现,这个B类就是设计的桥 。
桥接模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响。
举例说明:现需要提供大中小3种型号的画笔,能够绘制5种不同颜色,如果使用蜡笔,我们需要准备3*5=15支蜡笔,也就是说必须准备15个具体的蜡笔类。而如果使用毛笔的话,只需要3种型号的毛笔,外加5个颜料盒,用3+5=8个类就可以实现15支蜡笔的功能。
桥接模式的实现
桥接模式角色
- 抽象角色(Abstraction):一般为抽象类。该类持有一个实现角色的引用,并通过构造方法传入一个具体的实现类。
- 拓展抽象角色(RefinedAbstraction):扩展抽象角色,可以对抽象角色的方法进行覆盖重写来达到完善的目的。
- 实现角色(Implementor):定义一个维度的基本操作,提供给抽象角色使用,该类一般为接口或者抽象类。
- 具体实现角色(ConcreteImplementor):Implementor的具体实现类。
桥接模式类图
桥接模式举例
场景: 一个甜品蛋糕店,售卖的食品有蛋糕、奶茶和牛奶,但是每个商品都有各种口味:草莓味、蓝莓味、香蕉味。
食品又新增了提拉米苏,口味又新增了芒果,难道要把商品和口味再全部绑定一套吗?
显然这种两个维度扩展的情况不适合这种方案。那我们另辟蹊径,创建两个父类,一个食品类一个水果类。两个父类各自包含了相应的子类,然后根据需要将食品和水果进行组合。如下:
桥接模式代码实现
实现角色
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 水果
* @date 2023/07/09 14:08:10
*/
public interface Fruit {
/**
* 被添加
*
* @param food
*/
void doAdd(String food);
}
抽象角色
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 食物
* @date 2023/07/09 14:07:35
*/
public abstract class Food {
/**
* 水果
*/
Fruit fruit;
public void setFruit(Fruit fruit) {
this.fruit = fruit;
}
/**
* 制作时添加
*/
public abstract void add();
}
拓展抽象角色
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 蛋糕
* @date 2023/07/09 14:16:51
*/
public class Cake extends Food{
@Override
public void add() {
fruit.doAdd("蛋糕");
}
}
public class Milk extends Food{
@Override
public void add() {
fruit.doAdd("牛奶");
}
}
具体实现角色
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 香蕉
* @date 2023/07/09 14:09:02
*/
public class Banana implements Fruit{
@Override
public void doAdd(String food) {
System.out.println("香蕉" + food);
}
}
public class Blueberry implements Fruit{
@Override
public void doAdd(String food) {
System.out.println("蓝莓"+food);
}
}
public class Strawberry implements Fruit {
@Override
public void doAdd(String food) {
System.out.println("草莓" + food);
}
}
测试类
/**
* @author Evan Walker 昂焱数据: https://www.ayshuju.com
* @version 1.0
* @desc 测试类
* @date 2023/07/09 14:21:58
*/
public class Test {
public static void main(String[] args) {
//蛋糕
Fruit blueberry = new Blueberry();
Food cake = new Cake();
cake.setFruit(blueberry);
cake.add();
//牛奶
Food milk = new Milk();
milk.setFruit(blueberry);
milk.add();
}
}
测试结果
桥接模式的特点
优点
- 分离了抽象部分及其实现部分两个维度,实现了代码的解耦,提高了系统的扩展性。
- 扩展功能时只需要新增类,在两个变化维度中任意扩展一个维度,都不需要修改原有的系统,符合开闭原则。
- 通过组合而不是继承来实现耦合,符合组合复用原则。
- 桥接模式可替代多层继承方案,可以减少子类的个数,降低系统的管理和维护成本。
缺点
- 增加了系统的理解难度和设计难度,由于聚合关联关系建立在抽象层,需针对抽象进行设计与编程。
- 需要正确识别系统中各个独立变化的维度。
使用场景
- 当存在两个独立变化的维度,而这两个维度都需要进行扩展时
- 当不希望使用继承或因为多层次继承导致系统类的个数急剧增加时
- 当需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时,避免在两个层次之间建立静态的继承联系
注意事项
- 对于两个独立变化的维度,强烈推荐使用桥接模式,要求正确识别出系统中两个独立变化的维度,因此其使用范围有一定的局限性。对于系统的高层部分,只需要知道抽象部分和实现部分的接口就可以了,其他的部分由具体业务来完成。
- 桥接模式的实现形式来看,满⾜了单⼀职责和开闭原则,实现了抽象和实现部分的分离,提供了系统的灵活性,让抽象部分和实现部分相互独立,让每⼀部分内容都很清晰易于维护和拓展,但若实现的⾼内聚的代码,那么就会很复杂。所以在选择构建代码的时候,需要考虑好整体的设计,否则选不到合理的设计模式,将会让代码变得难以开发。
- 桥接模式是通过组合替代继承来实现的。在开发中需要解耦,解耦的实质就是减少对象之间的关联。继承是一种强关联,一旦通过继承,那么子类就会拥有父类所有公开的方法和属性,导致有些子类得到了不需要的方法和属性;而组合就不一样,组合是一种弱关联,我只是持有一个对象,但持有对象所拥有的功能并不是我的,和我并没有很强烈的关系。所以在很多场景都可通过组合来解耦继承对象之间的强关联关系。
希望大家记住编程中的一条原则:多用组合,少用继承。
更多消息资讯,请访问昂焱数据(https://www.ayshuju.com)