桥接模式

案例引入

对不同的手机类型和不同品牌实现操作(如开机,关机,上网,打电话等)。
如手机的类型有折叠式,直立式等。手机品牌有华为,小米,vivo等。

传统方式实现案例UML图

传统方式问题分析

  • 1.扩展性问题,如果再增加手机的样式,就需要增加各个品牌手机的类,同样我们如果增加一个手机品牌,也要在各个手机样式下增加类,很容易引起类爆炸问题。
  • 2.很多类,会有很大的代码维护成本。
  • 3.使用桥接模式解决。

基本介绍

  • 1.桥接模式(Bridge Pattern)是指,将实现和抽象放在两个不同的类层次中,使两个层次间可以独立改变。
  • 2.桥接模式是一种结构设计模式。
  • 3.桥接模式基于类的最小设计原则,通过使用封装,聚合及继承等行为,让不同的类承担不同的职责。它的主要特点就是把抽象(Abstraction)与实现(Implementation)分离开来,从而保持各部分的独立性以及应对其功能扩展。

桥接模式UML类图

类图说明
  • 1.Client类,桥接模式使用者。
  • 2.抽象类(Abstraction),维护了Implementor/即它的实现类,ConcreteImplementorA..,二者聚合,Abstraction充当桥接类。
  • 3.RefinedAbstraction,是Abstraction抽象类的子类。
  • 4.Implementor是行为实现类的接口。
  • 5.ConcreteImplementorA/B,行为的具体实现类。
  • 6.从UML图中看,抽象类和接口是聚合关系,其实是调用和被调用的关系。

桥接模式实现案例

UML图

代码
public interface Brand {


    public void open();
    public void close();
    public void call();
}
public class Vivo implements Brand{
    @Override
    public void call() {
        System.out.println("Vivo手机打电话");
    }

    @Override
    public void open() {
        System.out.println("Vivo手机开机");
    }

    @Override
    public void close() {
        System.out.println("Vivo手机关机");
    }
}
public class XiaoMi implements Brand{
    @Override
    public void call() {
        System.out.println("XiaoMi手机打电话");
    }

    @Override
    public void open() {
        System.out.println("XiaoMi手机开机");
    }

    @Override
    public void close() {
        System.out.println("XiaoMi手机关机");
    }
}
public abstract class Phone {

    private Brand brand;

    public Phone(Brand brand){
        this.brand = brand;
    }

    public Phone() {
    }

    public void open(){
        brand.open();
    }

    public void close(){
        brand.close();
    }

    public void call(){
        brand.call();
    }
}
public class FoldedPhone extends Phone{

    public FoldedPhone(Brand brand){
        super(brand);
    }

    public void open(){
        super.open();
        System.out.println("折叠样式手机");
    }

    public void close(){
        super.close();
        System.out.println("折叠样式手机");
    }

    public void call(){
        super.call();
        System.out.println("折叠样式手机");
    }
}
public class UpRightPhone extends Phone{

    public UpRightPhone(Brand brand){
        super(brand);
    }
    public void open(){
        super.open();
        System.out.println("直立样式手机");
    }

    public void close(){
        super.close();
        System.out.println("直立样式手机");
    }

    public void call(){
        super.call();
        System.out.println("直立样式手机");
    }
}
public class Client {
    public static void main(String[] args) {
        Phone vivo_phone = new FoldedPhone(new Vivo());
        vivo_phone.open();
        vivo_phone.call();
        vivo_phone.close();
        System.out.println("====================");
        Phone xiaoMi_phone = new UpRightPhone(new XiaoMi());
        xiaoMi_phone.open();
        xiaoMi_phone.call();
        xiaoMi_phone.close();
    }
}

桥接模式在JDBC源码分析

  • 1.JDBC的Driver接口,从桥接模式来看,Driver就是一个接口,下面有MySQL的Driver类,Oracle的Driver,这些就可以当作接口实现类
  • 2.核心代码
package com.mysql.cj.jdbc; //这是mysql包下的Driver
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    //
    // Register ourselves with the DriverManager
    //
    static {
        try {
            //注册mysql驱动
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }

    /**
     * Construct a new driver and register it with DriverManager
     * 
     * @throws SQLException
     *             if a database error occurs.
     */
    public Driver() throws SQLException {
        // Required for Class.forName().newInstance()
    }
}

说明,MySQL有自己的ConnectionImpl类,MySQL的Driver和Connection之间是通过DriverManager(java.sql)的类进行桥连接的。

UML图

注意事项和细节

  • 1.实现了抽象和实现部分的分离,从而极大的提供了系统的灵活性,让抽象部分和实现部分独立开来,这有助于系统进行分层设计,从而产生更好的结构化系统。
  • 2.对于系统的高层部分,只需要知道抽象部分和实现部分的接口就可以了,其它的部分由具体业务来完成。
  • 3.桥接模式替代多层继承方案,可以减少子类的个数,降低系统的管理和维护成本。
  • 4.桥接模式的引入增加了系统的理解和设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计和编程
  • 5.桥接模式要求正确识别出系统中两个独立变化的维度(抽象、和实现),因此其使用范围有一定的局限性,即需要有这样的应用场景。

桥接模式应用场景举例

1.对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用.
2.常见的应用场景:

  • -JDBC驱动程序
  • -银行转账系统
    转账分类: 网上转账,柜台转账,ATM转账
    转账用户类型: 普通用户,银卡用户,金卡用户..
  • -消息管理
    消息类型: 即时消息,延时消息
    消息分类: 手机短信,邮件消息,QQ消息...

只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。