设计模式结构型——桥接模式

桥接模式是一种设计模式,用于分离抽象和实现,使得两者可以独立变化,提高系统的扩展性。它通过接口或抽象类实现抽象和实现的解耦,允许在两个独立变化的维度中任意扩展。文章提供了桥接模式的角色、类图、优点、缺点、使用场景和代码示例,如食品和口味的例子,展示如何通过桥接模式减少类的数量并增加灵活性。
摘要由CSDN通过智能技术生成

目录

什么是桥接模式

桥接模式的实现

桥接模式角色

桥接模式类图

桥接模式举例

桥接模式代码实现

桥接模式的特点

优点

缺点

使用场景

注意事项


什么是桥接模式

        桥接(Bridge)模式是用于把抽象化与实现化解耦,使得二者可以独立变化。把抽象(abstraction)与行为实现(implementation)分离开来,从而可以保持各部分的独立性以及应对它们的功能扩展。其归属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。

        说⽩了核⼼实现也就是在A类中含有B类接口,通过构造函数传递B类的实现,这个B类就是设计的桥 。

        桥接模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响。

        举例说明:现需要提供大中小3种型号的画笔,能够绘制5种不同颜色,如果使用蜡笔,我们需要准备3*5=15支蜡笔,也就是说必须准备15个具体的蜡笔类。而如果使用毛笔的话,只需要3种型号的毛笔,外加5个颜料盒,用3+5=8个类就可以实现15支蜡笔的功能。

桥接模式的实现

桥接模式角色

  1. 抽象角色(Abstraction):一般为抽象类。该类持有一个实现角色的引用,并通过构造方法传入一个具体的实现类。
  2. 拓展抽象角色(RefinedAbstraction):扩展抽象角色,可以对抽象角色的方法进行覆盖重写来达到完善的目的。
  3. 实现角色(Implementor):定义一个维度的基本操作,提供给抽象角色使用,该类一般为接口或者抽象类。
  4. 具体实现角色(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();
    }

}

测试结果

桥接模式的特点

优点

  1. 分离了抽象部分及其实现部分两个维度,实现了代码的解耦,提高了系统的扩展性。
  2. 扩展功能时只需要新增类,在两个变化维度中任意扩展一个维度,都不需要修改原有的系统,符合开闭原则。
  3. 通过组合而不是继承来实现耦合,符合组合复用原则。
  4. 桥接模式可替代多层继承方案,可以减少子类的个数,降低系统的管理和维护成本。

缺点

  1. 增加了系统的理解难度和设计难度,由于聚合关联关系建立在抽象层,需针对抽象进行设计与编程。
  2. 需要正确识别系统中各个独立变化的维度。

使用场景

  1. 当存在两个独立变化的维度,而这两个维度都需要进行扩展时
  2. 当不希望使用继承或因为多层次继承导致系统类的个数急剧增加时
  3. 当需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时,避免在两个层次之间建立静态的继承联系

注意事项

  1. 对于两个独立变化的维度,强烈推荐使用桥接模式,要求正确识别出系统中两个独立变化的维度,因此其使用范围有一定的局限性。对于系统的高层部分,只需要知道抽象部分和实现部分的接口就可以了,其他的部分由具体业务来完成。
  2. 桥接模式的实现形式来看,满⾜了单⼀职责和开闭原则,实现了抽象和实现部分的分离,提供了系统的灵活性,让抽象部分和实现部分相互独立,让每⼀部分内容都很清晰易于维护和拓展,但若实现的⾼内聚的代码,那么就会很复杂。所以在选择构建代码的时候,需要考虑好整体的设计,否则选不到合理的设计模式,将会让代码变得难以开发。
  3. 桥接模式是通过组合替代继承来实现的。在开发中需要解耦,解耦的实质就是减少对象之间的关联。继承是一种强关联,一旦通过继承,那么子类就会拥有父类所有公开的方法和属性,导致有些子类得到了不需要的方法和属性;而组合就不一样,组合是一种弱关联,我只是持有一个对象,但持有对象所拥有的功能并不是我的,和我并没有很强烈的关系。所以在很多场景都可通过组合来解耦继承对象之间的强关联关系。

希望大家记住编程中的一条原则:多用组合,少用继承。
 

更多消息资讯,请访问昂焱数据(https://www.ayshuju.com)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值