设计模式轻松学【二十】桥接模式

简介: 小明有台联想电脑,他买来时预安装的是Windows系统,但是它也想尝试Linux系统或其他系统。财大气粗的小明于是又花了5000去购买了台内置的Linux系统。其实它完全可以在原来电脑上安装Linux系统,不必再去买一台。在现实生活中也有很多这样的例子,一个物品在搭配不同的配件时会产生不同的动作和结果。

我们从软件角度来分析,一个系统由于自身的逻辑,会有两个或多个维度的变化,应对这种变化,我们可以使用桥接模式来进行系统的解耦。

模式定义与特点

  • 定义:将抽象与实现分离,使它们可以独立变化,它是一种对象结构型模式。

    桥接模式可以将一个系统的抽象部分和实现部分分离,使它们都可以独立地进行变化。对应到上述例子中就是:电脑的型号可以自由变化,电脑内置的操作系统也可以自由变化,这样不同的维度能够组合出多种实际的结果。

  • 参与角色

    • 抽象化角色(Abstraction):定义抽象类,并包含一个对实现化对象的引用。
    • 扩展抽象化角色(Refine Abstraction):是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
    • 实现化(Implementor)角色:定义实现化角色的接口,不给出具体的实现,供扩展抽象化角色调用
    • 具体实现化(Concrete Implementor)角色:给出实现化角色接口的具体实现
  • 类结构图

    image.png

    抽象化角色就像是一个水杯的手柄,而实现化角色和具体实现化角色就像是水杯的杯身。

  • 结构代码示例

    • 实现化角色

      abstract class Implementor {
          /**
           * 抽象方法,实现抽象部分需要的某些功能
           */
          public abstract void operation1();
      }
    • 具体实现化角色

      class ConcreteImplementorA extends Implementor {
          @Override
          public void operationImpl() {
              //具体操作
          }
      }
      
      class ConcreteImplementorB extends Implementor {
          @Override
          public void operationImpl() {
              //具体操作
          }
      }
    • 抽象化角色类

      它声明了一个方法operation(),并给出了它的实现。这个实现是通过向实现化对象的委派(也就是调用实现化对象的operationImpl()方法)实现的。

      abstract class Abstraction {
          protected Implementor implementor;
      
          public Abstraction(Implementor implementor) {
              this.implementor = implementor;
          }
      
          /**
           * 示例方法
           */
          public void operation() {
              implementor.operationImpl();
          }
      }
    • 扩展抽象化角色

      class RefinedAbstraction extends Abstraction {
          public RefinedAbstraction(Implementor implementor) {
              super(implementor);
          }
      
          /**
           * 其他的操作方法
           */
          public void otherOperation() {
              //对 Abstraction 中的 operation 方法进行扩展
          }
      }

      一般而言,实现化角色中的每个方法都应当有一个抽象化角色中的某一个方法与之对应,但是反过来则不一定。换而言之,抽象化角色的接口比实现化角色的接口宽。抽象化角色除了提供与实现化角色相关的方法之外,还有可能提供其他的方法;而实现化角色则往往仅为实现抽象化角色的相关行为而存在。

    • 客户端调用

      public class BridgeTest{
          public static void main(String[] args)    {
              Implementor impl = new ConcreteImplementorA();
              Abstraction abs = new RefinedAbstraction(impl);
              abs.operation();
          }
      }

案例分析

桥接(Bridge)模式模拟女士皮包的选购。

女士皮包有很多种,可以按用途分、按皮质分、按品牌分、按颜色分、按大小分等,存在多个维度的变化,所以采用桥接模式来实现女士皮包的选购比较合适。

本实例按用途分可选钱包(Wallet)和挎包(HandBag),按颜色分可选黄色(Yellow)和红色(Red)。可以按两个维度定义为颜色类和包类。

颜色类(Color)是一个维度,定义为实现化角色,它有两个具体实现化角色:黄色和红色,通过 getColor() 方法可以选择颜色;包类(Bag)是另一个维度,定义为抽象化角色,它有两个扩展抽象化角色:挎包和钱包,它包含了颜色类对象,通过 getName() 方法可以选择相关颜色的挎包和钱包。

image.png

  • 实现化角色

    interface Color {
        abstract String getColor() ;
    }
  • 具体实现化角色

    //具体实现话角色1
    class Yello implements Color{
    
        @Override
        public String getColor() {
            return "黄色";
        }
    }
    //具体实现话角色2
    class Red implements Color{
        
        @Override
        public String getColor() {
            return "红色";
        }
    }
  • 抽象化角色

    abstract class Bag {
        private Color color;
        
        public void setColor(Color color) {
            this.color = color;
        }
        abstract String getName() ;
    }
  • 扩展抽象化角色

    //扩展抽象化角色1
    class HandBag extends Bag{
    
        @Override
        String getName() {
            return color.getColor() + "HandBag";
        }
    }
    //扩展抽象化角色2
    class Wallet extends Bag{
        
        @Override
        String getName() {
            return color.getColor() + "Wallet";
        }
    }
  • 调用客户端

    public class Client {
        
        public static void main(String[] args) {
            //实例化一个手提包
            Bag bag = new HandBag();
            //设置颜色为黄色
            bag.setColor(new Yello());
            //获取:手提包+黄色的组装
            String yelloHandBag = bag.getName();
            System.out.println(yelloHandBag);
            
            System.out.println("------------");
            
            bag.setColor(new Red());
            String redHandBag = bag.getName();
            System.out.println(redHandBag);
        }
    }

这样我们将颜色和包都抽离出来后,可自由进行组合桥接,在软件开发中如果一个类或一个系统有多个变化维度时,都可以尝试使用桥接模式对其进行设计。桥接模式为多维度变化的系统提供了一套完整的解决方案,并且降低了系统的复杂度。

总结

  1. 优点

    • 分离抽象接口及其实现部分。桥接模式使用“对象间的关联关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。所谓抽象和实现沿着各自维度的变化,也就是说抽象和实现不再在同一个继承层次结构中,而是“子类化”它们,使它们各自都具有自己的子类,以便任何组合子类,从而获得多维度组合对象
    • 在很多情况下,桥接模式可以取代多层继承方案,多层继承方案违背了“单一职责原则”,复用性较差,且类的个数非常多,桥接模式是比多层继承方案更好的解决方法,它极大减少了子类的个数
    • 桥接模式提高了系统的可扩展性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统,符合“开闭原则”
  2. 缺点

    • 桥接模式的使用会增加系统的理解与设计难度,由于关联关系建立在抽象层,要求开发者一开始就针对抽象层进行设计与编程。
    • 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性,如何正确识别两个独立维度也需要一定的经验积累。
  3. 适用场景

    • 如果一个系统需要在抽象化和具体化之间增加更多的灵活性,避免在两个层次之间建立静态的继承关系,通过桥接模式可以使它们在抽象层建立一个关联关系。
    • “抽象部分”和“实现部分”可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。
    • 一个类存在两个(或多个)独立变化的维度,且这两个(或多个)维度都需要独立进行扩展。
    • 对于那些不希望使用继承或因为多层继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
目录
相关文章
|
5月前
|
设计模式 开发者
【设计模式】第七篇:和我一起简单认识桥接模式
实现的意思并不是指抽象的派生类,而是指通过组合来代替继承关系,从而降低抽象和具体实现产品两个可变换维度之间的耦合,就像我们的相机品牌和相机产品类型之间的分离
52 4
|
6月前
|
设计模式 Java
【设计模式】JAVA Design Patterns——Bridge(桥接模式)
【设计模式】JAVA Design Patterns——Bridge(桥接模式)
【设计模式】JAVA Design Patterns——Bridge(桥接模式)
|
6月前
|
设计模式 Oracle Java
设计模式--- 桥接模式、JDBC 源码剖析(桥接)
设计模式--- 桥接模式、JDBC 源码剖析(桥接)
122 2
|
6月前
|
设计模式
设计模式之桥接模式
设计模式之桥接模式
|
6月前
|
设计模式 Linux Windows
【设计模式】桥接模式
【设计模式】桥接模式
|
1月前
|
设计模式 PHP 开发者
PHP中的设计模式:桥接模式的解析与应用
在软件开发的浩瀚海洋中,设计模式如同灯塔一般,为开发者们指引方向。本文将深入探讨PHP中的一种重要设计模式——桥接模式。桥接模式巧妙地将抽象与实现分离,通过封装一个抽象的接口,使得实现和抽象可以独立变化。本文将阐述桥接模式的定义、结构、优缺点及其应用场景,并通过具体的PHP示例代码展示如何在实际项目中灵活运用这一设计模式。让我们一起走进桥接模式的世界,感受它的魅力所在。
|
2月前
|
设计模式 自然语言处理 算法
PHP中的设计模式:桥接模式的深入探索与应用
在PHP开发中,理解并运用设计模式是提升代码质量与可维护性的关键。本文聚焦于桥接模式——一种结构型设计模式,它通过封装一个抽象的接口,将实现与抽象分离,从而使得它们可以独立变化。不同于传统摘要的概述式表述,本文将以故事化的情境引入,逐步解析桥接模式的精髓,通过PHP代码示例详细展示其在实际项目中的应用,旨在为读者提供一个既深刻又易于理解的学习体验。
27 1
|
2月前
|
设计模式 Java
Java设计模式-桥接模式(9)
Java设计模式-桥接模式(9)
|
1月前
|
设计模式 Java
Java设计模式之桥接模式
这篇文章介绍了Java设计模式中的桥接模式,包括桥接模式的目的、实现方式,并通过具体代码示例展示了如何分离抽象与实现,使得两者可以独立变化。
44 0
|
3月前
|
设计模式 XML 存储
【七】设计模式~~~结构型模式~~~桥接模式(Java)
文章详细介绍了桥接模式(Bridge Pattern),这是一种对象结构型模式,用于将抽象部分与实现部分分离,使它们可以独立地变化。通过实际的软件开发案例,如跨平台视频播放器的设计,文章阐述了桥接模式的动机、定义、结构、优点、缺点以及适用场景,并提供了完整的代码实现和测试结果。桥接模式适用于存在两个独立变化维度的系统,可以提高系统的可扩展性和灵活性。
【七】设计模式~~~结构型模式~~~桥接模式(Java)

热门文章

最新文章

  • 1
    C++一分钟之-设计模式:工厂模式与抽象工厂
    43
  • 2
    《手把手教你》系列基础篇(九十四)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-下篇(详解教程)
    50
  • 3
    C++一分钟之-C++中的设计模式:单例模式
    58
  • 4
    《手把手教你》系列基础篇(九十三)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-上篇(详解教程)
    38
  • 5
    《手把手教你》系列基础篇(九十二)-java+ selenium自动化测试-框架设计基础-POM设计模式简介(详解教程)
    63
  • 6
    Java面试题:结合设计模式与并发工具包实现高效缓存;多线程与内存管理优化实践;并发框架与设计模式在复杂系统中的应用
    58
  • 7
    Java面试题:设计模式在并发编程中的创新应用,Java内存管理与多线程工具类的综合应用,Java并发工具包与并发框架的创新应用
    42
  • 8
    Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
    50
  • 9
    Java面试题:请列举三种常用的设计模式,并分别给出在Java中的应用场景?请分析Java内存管理中的主要问题,并提出相应的优化策略?请简述Java多线程编程中的常见问题,并给出解决方案
    110
  • 10
    Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
    78
  • 下一篇
    无影云桌面