重温设计模式:桥接模式实现灵活组合,超越单一继承的设计之道

文摘   科技   2024-09-22 22:14   广东  


一、什么是桥接设计模式

桥接模式是一种非常实用的设计模式,它帮我们解决了一个常见的问题:当一个类存在多个维度(或称角度、属性)的变化时,如何避免因为维度间的组合而导致子类数量的爆炸式增长。用更通俗易懂的话来说,桥接模式就像是在搭积木,我们把不同的积木块(代表不同的维度或特性)分开设计,然后在需要的时候再把它们组合起来,这样不仅能减少重复代码,还能让各个积木块(维度)能够独立变化,互不影响。

正经点说,桥接模式将一个大的或复杂的类拆分为两个独立的层次结构:抽象层次结构和实现层次结构。抽象层次结构定义了操作的接口,而实现层次结构则提供了这些操作的具体实现。这两个层次结构之间通过一个引用(桥梁)进行连接,从而实现了抽象与实现的解耦。

二、桥接设计模式的核心思想

桥接设计模式的核心思想是“组合优于继承”。这一思想强调通过组合(即对象之间的关联关系)来实现代码的复用和扩展,而不是通过继承(即类之间的层级关系)。


继承是一种强大的代码复用机制,过度使用也会导致代码的可读性下降、维护成本增加以及灵活性降低等问题。特别是当继承层次过深或过于复杂时,这些问题会变得更加明显。

桥接设计模式通过引入一个抽象层(即桥梁)来分离接口和其具体实现,从而避免了继承带来的这些问题。在这个抽象层中,可以定义一些抽象的操作或方法,这些方法将委托给具体的实现对象来执行。这样,抽象部分和实现部分就可以通过组合关系进行连接,而不是通过继承关系。

这种组合关系带来了几个好处

  • 减少了代码之间的耦合度。由于抽象部分和实现部分是独立的,可以在不修改其他部分的情况下更改或替换其中的一部分。

  • 提高了代码的灵活性和可扩展性。可以根据需要动态地组合不同的抽象部分和实现部分,从而创建出满足特定需求的新对象或功能。

  • 代码更清晰和易于维护。通过将抽象和实现分离,可以更容易地理解和修改代码的各个部分,从而提高了代码的可读性和可维护性。

三、桥接设计模式的角色

桥接设计模式中,涉及以下几个关键角色:


  1. Abstraction(抽象):定义一个抽象类,它包含一个对实现对象的引用(通常是接口类型)。这个抽象类将定义一些操作,这些操作将委托给具体的实现对象来执行。

  2. RefinedAbstraction(精化抽象):继承自Abstraction,并为核心抽象增加新的功能。这些功能可能会使用也可能不使用实现对象提供的操作。

  3. Implementor(实现者接口):定义实现对象的接口,该接口声明了实现对象需要提供的具体操作。

  4. ConcreteImplementor(具体实现者):实现Implementor接口,提供具体操作的实现。

四、桥接设计模式的工作流程和实现

在桥接设计模式中,抽象与实现之间的交互通常遵循以下步骤:

  • 客户端创建一个RefinedAbstraction对象,该对象包含一个指向某个ConcreteImplementor对象的引用。


  • 客户端通过调用RefinedAbstraction对象的方法来执行某些操作。


  • 在RefinedAbstraction对象中,这些操作被委托给其包含的ConcreteImplementor对象来实际执行。


  • 如果需要更换具体的实现,只需要改变RefinedAbstraction对象中引用的ConcreteImplementor对象即可,无需修改RefinedAbstraction对象本身的代码。


实现方式一:使用接口与实现类

  1. 定义实现者接口(Implementor)
// 实现者接口定义了操作的契约interface Implementor {
void operationImpl(); // 定义需要实现的操作}
  1. 定义具体实现者(ConcreteImplementor)
// 具体实现者A实现了实现者接口class ConcreteImplementorA implements Implementor {      @Override    public void operationImpl() {        System.out.println("具体实现者A的操作实现");    }}
// 可有多个具体实现者class ConcreteImplementorB implements Implementor { @Override public void operationImpl() {        System.out.println("具体实现者B的操作实现"); }}
  1. 定义抽象类(Abstraction)
// 抽象类持有一个对实现者接口的引用abstract class Abstraction {
protected Implementor implementor; public Abstraction(Implementor implementor) { this.implementor = implementor; } public void operation() { // 调用实现者的操作,可能包括一些抽象类自己的逻辑 implementor.operationImpl(); }}
  1. 定义精化抽象类(RefinedAbstraction)
// 精化抽象类继承自抽象类,可增加额外的操作class RefinedAbstraction extends Abstraction {
public RefinedAbstraction(Implementor implementor) { super(implementor); } public void refinedOperation() { // 精化操作,可以调用或不调用实现者的操作 System.out.println(" 精化抽象类的额外操作"); super.operation();         // 可选择性地调用父类的操作 }}
  1. 客户端代码
public class BridgePatternClient {    public static void main(String[] args) {        //  具体实现者        Implementor implementorA = new ConcreteImplementorA();        Implementor implementorB = new ConcreteImplementorB();                //  精化抽象类对象,并传入不同的实现        Abstraction abstractionA = new RefinedAbstraction(implementorA);        Abstraction abstractionB = new RefinedAbstraction(implementorB);                //  调用        abstractionA.operation();         // 输出:具体实现者A的操作实现        ((RefinedAbstraction) abstractionB).refinedOperation();         // 输出:精化抽象类的额外操作 和 具体实现者B的操作实现    }}

实现方式二:使用抽象类与实现类

这种方式中,需将接口Implementor替换为抽象类,其余结构与方式一类似。这种方式提供了更多的灵活性,允许在实现者之间共享一些状态或行为。

// 将Implementor接口改为抽象类,并添加一些共享的状态或行为...abstract class Implementor {    public void sharedOperation() {        // 共享的操作实现...    }        public abstract void operationImpl();     // 仍然是抽象方法,需要具体实现者来实现}

具体实现者将继承这个抽象类,并提供operationImpl方法的实现。其余的代码结构与方式一保持一致。优点是可以在不同的实现者之间共享代码,但缺点是可能引入更多的继承层级。选择哪种方式取决于具体的应用场景和需求。

五、桥接模式的适用场景

桥接设计模式的适用场景包括但不限于:

1. 多维度的变化:当一个类有多个独立变化的维度时,使用桥接模式可以将这些维度分离,使得每个维度都可以独立扩展,而不会影响到其他维度。
2. 避免类爆炸:继承方式在复杂多维度变化时,会导致类爆炸。桥接模式通过分离抽象和实现,减少了类的数量。
3. 提高扩展性:桥接模式使得在不修改现有代码的情况下,可以轻松地添加新的实现或抽象,提高了系统的扩展性和可维护性。

太强 ! SpringBoot中出入参增强的5种方法 : 加解密、脱敏、格式转换、时间时区处理

太强 ! SpringBoot中优化if-else语句的七种绝佳方法实战
SpringBoot使用EasyExcel并行导出多个excel文件并压缩zip下载
经典八股:Redis数据结构与底层实现揭秘
玩转同步控制:LockSupport深入解读
90分掌握一门语言:lua脚本基础到高级教程
提升编程效率的利器: Google Guava库中双向映射BitMap
从MySQL行格式原理看:为什么开发规范中不推荐NULL?数据是如何在磁盘上存储的?
SpringBoot中使用Jackson实现自定义序列化和反序列化控制的5种方式总结
提升编程效率的利器: Google Guava库之RateLimiter优雅限流
深入JVM逃逸分析原理:且看其如何提高程序性能和内存利用率
必知必会!MySQL索引下推:原理与实战

深入解析JVM内存分配优化技术:TLAB

SpringBoot中基于JWT的双token(access_token+refresh_token)授权和续期方案
SpringBoot中基于JWT的单token授权和续期方案
SpringBoot中Token登录授权、续期和主动终止的方案(Redis+Token)
微服务中token鉴权设计的4种方式总结

关注『 码到三十五 』,日有所获
                  点赞 和 在看 就是最大的支持

    码到三十五
    主要分享正经的开发技术(原理,架构,实践,源码等),以输出驱动输入;当然偶尔会穿插点生活琐碎,顺便吃个瓜,目的嘛,搞点精准流量,看能不能发发广告。
     最新文章