【Java设计模式】结构型设计模式-桥接模式(九)

桥接模式

  • 桥接模式属于结构型设计模式。
  • 桥接模式将实现和抽象放在两个或两个以上不同的类层次中,使两个或两个以上层次可以独立改变。
  • 桥接模式是基于类的最小设计原则,通过使用封装、聚合、组合和继承的方式让不同的类承担不同的职责,它的主要特点是将抽象和行为实现分离开来,从而可以保证各部分的独立性以及应对它们之后的扩展。

进一步阐述:是用于解决多重继承结构,多维度变化的场景,将各个维度设计成独立的继承结构,使各个维度可以独立的扩展在抽象层建立关联。

桥接模式包含四种角色:

  • Abstraction(抽象角色): 抽象的定义,并保存一个Implementor对象的引用。
  • RefineAbstraction(扩展抽象角色): 继承Abstraction并对其进行拓展。
  • Implementor(抽象实现角色): 定义实现类的接口,提供基本操作,其具体的操作交给子类实现。
  • ConcreteImplementor(具体实现角色): 实现Implementor接口,在程序运行时,子类对象将替换其父类对象,提供给Abstraction具体的业务操作方法。

案例:以家用电器和品牌桥接为例,其中电器类ElectricAppliance就是抽象角色,冰箱Refrigerator类和空调Conditioner类就是扩展抽象角色,品牌接口Brand就是抽象实现角色,海尔Haier类和格力Gree类就是具体实现角色。

UML类图:

客户端Client类:

java 复制代码
/**
 * 使用桥接模式的客户端
 */
public class Client {
​
    public static void main(String[] args) {
        //使用海尔冰箱
        ElectricAppliance elcApp1 = new Refrigerator(new Haier());
        elcApp1.running();
        System.out.println("==========================");
        //使用格力空调
        ElectricAppliance elcApp2 = new Conditioner(new Gree());
        elcApp2.running();
    }
}

电器ElectricAppliance抽象类:

java 复制代码
/**
 * 电器抽象类(相当于抽象角色)
 * 充当了桥接的角色(桥梁),将电器和品牌两个抽象角色连接起来。
 */
public abstract class ElectricAppliance {
​
    /*
     * 电器品牌
     */
    protected Brand elcAppBrand;
​
    public ElectricAppliance(Brand elcAppBrand) {
        this.elcAppBrand = elcAppBrand;
    }
​
    /**
     * 运行方式
     */
    public abstract void running();
​
}

冰箱Refrigerator类:

java 复制代码
/**
 * 冰箱类(相当于扩展抽象角色)
 */
public class Refrigerator extends ElectricAppliance {
​
    public Refrigerator(Brand brand) {
        super(brand);
    }
​
    @Override
    public void running() {
        elcAppBrand.running("冰箱");
    }
}

空调Conditioner类:

java 复制代码
/**
 * 空调类(相当于扩展抽象角色)
 */
public class Conditioner extends ElectricAppliance {
​
    public Conditioner(Brand brand) {
        super(brand);
    }
​
    @Override
    public void running() {
        elcAppBrand.running("空调");
    }
}

品牌Brand接口:

java 复制代码
/**
 * 品牌接口(相当于抽象实现角色)
 */
public interface Brand {
​
    /**
     * 运行方法
     */
    void running(String type);
}

海尔品牌Haier实现类:

java 复制代码
/**
 * 海尔品牌实现类(相当于具体实现角色)
 */
public class Haier implements Brand {
​
    private String name = "海尔";
​
    @Override
    public void running(String type) {
        System.out.println("以" + name + type + "的方式运行......");
    }
}

格力品牌Gree实现类:

java 复制代码
/**
 * 格力品牌实现类(相当于具体实现角色)
 */
public class Gree implements Brand {
​
    private String name = "格力";
​
    @Override
    public void running(String type) {
        System.out.println("以" + name + type + "的方式运行......");
    }
}

总结:

  • 实现了抽象部分和实现部分的分离,从而极大的提高了系统的灵活性,让抽象部分和实现部分独立开来,这也有助于系统进行分层设计,从而产生更好的结构化系统。
  • 对于系统的调用者,只需要知道抽象部分的类和实现部分的接口就可以了,其它的部分由具体业务来完成。
  • 桥接模式可以取代多重继承的方案,因为多重继承违反了单一职能原则,因此可复用性、可维护性很差,类的个数也会随着扩展而变得特别庞大。而使用桥接模式可以极大的减少子类的个数,从而降低管理和维护的成本,所以遵守了单一职能原则。
  • 桥接模式极大地提高了系统可扩展性,在两个或两个以上变化维度中任意扩展一个维度,都不需要修改原有的系统,因此遵守了开闭原则(OCP原则)。
  • 使用桥接模式需要识别出系统中两个独立变化的部分,加大了设计和维护的难度,由于关联关系建立在抽象层,所以要求开发者针对抽象进行设计和编程。
  • 桥接模式和装饰者模式的区别:
    • 抽桥接模式的目的是为了将象部分与实现部分分离,使他们都可以独立地进行变化,所以说他们两个部分是独立的,没有实现或继承自同一个接口。
    • 两个模式都是为了解决过扩展时使用继承的方式产生的很多子类对象问题。但它们解决问题的目的完全不一样。桥接模式是为了解决对象自身现有机制沿着会多个维度变化的情况(即解决多重继承问题)而产生的,它的原有部分是不稳定的。装饰模式是为了增加新的功能而原有部分是较为稳定的,原有部分是主体。

典型运用场景举例: 对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。例如:

  • 支付系统中的账单管理:
    • 按操作类型分类:购物类账单、转账类账单、借贷类账单等等。
    • 按平台分类:花呗账单、余额宝账单、支付宝余额账单。
  • 电商系统中的优惠活动计算价格管理:
    • 按满减分类:满100减5元,满300减20元,满500减40元。
    • 按折扣分类:全场商品9.8折、全场商品9.5折、全场商品9折。
  • 物流管理系统的包裹管理:
    • 按运送紧急程度分类:普通包裹、快递包裹、特快包裹。
    • 按收件方式分类:货到付款类、到付邮费类、先付邮费类。
相关推荐
贫民窟的勇敢爷们1 小时前
SpringBoot整合AOP切面编程实战,实现日志统一记录+接口权限校验
java·spring boot·spring
candyTong2 小时前
Claude Code Agent Teams:多 Agent 协作的生命周期与实现机制
后端·架构
AC赳赳老秦2 小时前
供应链专员提效:OpenClaw自动跟踪物流信息、更新库存数据,异常自动提醒
java·大数据·服务器·数据库·人工智能·自动化·openclaw
迈巴赫车主2 小时前
Java基础:list、set、map一遍过
java·开发语言
灵犀学长3 小时前
基于 Spring ThreadPoolTaskScheduler + CronTrigger 实现的动态定时任务调度系统
java·数据库·spring
好家伙VCC4 小时前
【无标题】
java
小碗羊肉5 小时前
【JavaWeb | 第十一篇】文件上传(本地&阿里云OSS)
java·阿里云·servlet
吾疾唯君医5 小时前
Java SpringBoot集成积木报表实操记录
java·spring boot·spring·导出excel·积木报表·数据文件下载
Byron Loong5 小时前
【c++】为什么有了dll和.h,还需要包含lib
java·开发语言·c++
hexu_blog6 小时前
vue+java实现图片批量压缩
java·前端·vue.js