小言_互联网的博客

桥接模式

260人阅读  评论(0)
(一)介绍

桥接模式即将抽象部分与它的实现部分分离开来,使他们都可以独立变化。
桥接模式将继承关系转化成关联关系,它降低了类与类之间的耦合度,减少了系统中类的数量,也减少了代码量。

(二)核心特性

1:继承关系转化成关联关系
2:抽象部分与他的实现部分分离
3:将类的功能层次结构和实现层次结构分离
4:桥接模式的作用就是连接类的功能层次结构和实现层次结构(聚合)

(三)类的功能层次结构和实现层次结构

1:类的功能层次结构
此时我们有一个类,具有一个功能,但是现在我想新增一个功能,不要去修改原类结构,那么此时我我可以通过继承去生成该类的子类,在子类中新增这个功能,此时子类就具有了俩个功能,同理,如果还要添加功能,继续新增子类,这样就呈现出了一种层次增加功能的结构

当要增加新的功能时,我们可以从各个层次的类中找出最符合自己需求的类,然后以它为父类编写子类,并在子类中增加新的功能.这就是类的功能层次结构.
2:类的实现层次结构

编程语言中,抽象类的作用是声明一些抽象方法,定义了接口(API),然后子类负责去实现这些抽象方法.父类的任务是通过声明抽象方法的方式定义接口(API),而子类的任务是实现抽象方法.正是由于父类和子类的这种任务分担,我们才可以编写出具有高可替换的类。而这里其实也存在层次结构,例如:当子类ConcreteClass实现了父类AbstractClass类的抽象方法时,他们之间就构成了一个小小的层次结构.

但是这里类的层次结构并非用于增加功能,也就是说,这种层次结构并非用于方便我们增加新的方法.它的真正作用是帮助我们实现下面这样的任务分担

—父类通过声明抽象方法定义接口(API)
—子类通过实现具体方法来实现接口(API)

这种层次的结构被称为类的实现层次结构
当我们以其他方式实现AbstractClass时,例如要实现一个AnotherConcreteClass时,类的层次结构会稍微发生一些变化

为了一种新的实现方法,我们继承了AbstractClass的子类,并实现了其中的抽象方法,这就是类的实现层次结构

(四)桥接模式结构分析


我们看一下上面的类图,将该类图与前面提及的类的功能层次结构和实现层次结构关联.
左边的部分就是类的功能层次部分,其中Display是一个基类,他提供一个display的功能,而在CountDisplay中继承了该类并且新增自己的一个功能.
右边的部分DisplayImpl是一个抽象类,定义了基本的接口API,该类有一个实现的子类StringDisplayImpl提供了具体的实现.右边整体呈现就是类的实现结构
左右边的关联是通过聚合的方式,在Display中持有DisplayImpl实例属性,通过该属性完成自己具体功能的实现
上面的类图看起来简单,但其实就代表一个完整的桥接模式,如果想要扩展就完全可以新增功能子类和实现.进一步扩展.

(五)代码实例

以下代码实现的展示数据的功能,具体的实现是由DisplayImpl子类完成,CountDisplay增加可以动态显示多次的功能

public class Display {
    
    DisplayImpl displayImpl;

    public Display(DisplayImpl displayImpl) {
        this.displayImpl = displayImpl;
    }
    void open() {
      displayImpl.rawOpen();
    }

    void print() {
     displayImpl.rawPrint();
    }

    void close() {
        displayImpl.rawClose();
    }

    void display() {
        open();
        print();
        close();
  }
}
public class CountDisplay extends Display {
    public CountDisplay(DisplayImpl displayImpl) {
        
        super(displayImpl);
    }
    void multiDisplay(int times) {
        open();
        for (int i = 0; i < times; i++) {
            print();
        }
        close();
    }
}
public abstract class DisplayImpl {

    abstract void rawOpen();

    abstract void rawPrint();

    abstract void rawClose();


}
public class StringDisplayImpl extends DisplayImpl {

    @Override
    void rawOpen() {
        
        System.out.println("******启动*****");
    }

    @Override
    void rawPrint() {
        
        System.out.println("******HelloWorld*****");
    }

    @Override
    void rawClose() {
        System.out.println("******关闭*****");
    }
}
public class Main {

    public static void main(String[] args) {
        //创建具体实现层
        DisplayImpl displayImpl = new StringDisplayImpl();
        //将实现层桥接到功能层上
        Display display = new CountDisplay(displayImpl);
        CountDisplay countDisplay = new CountDisplay(displayImpl);
        display.display();
        countDisplay.multiDisplay(3);

    }
}

(六)角色介绍

Abstract(抽象化)—Display
该角色位于类的功能层次结构的最上层,它使用Implementor角色的方式定义了基本的功能.该角色中保存了Implementor的实例

RefinedAbstraction(改善后的抽象化)—CountDisplay
在Abstraction角色的基础上增加了新功能的角色

Implementor(实现者)—DisplayImpl
该角色位于类的实现层次结构的最上层.定义了用于实现Abstraction角色的接口API的方法

ConcreteImplementor(具体的实现者)—StringDisplayImpl
该角色负责在Implementor角色中定义的接口

桥接者
桥接者对象负责的就是链接功能层次和实现层次,本次代码中桥接者的对象就是Display中的 DisplayImpl displayImpl;实例

(七)扩展

继承是强关联,委托是弱关联

虽然使用继承很容易扩展类,但是类之间也形成了一种强关联关系.例如,在下面的代码中,SomethingGood类是Something的子类,但只要不修改代码,就无法改变这种关系,因此可以说他们之间形成了一种强关联关系:
如果想要很轻松地改变类之间的关系,使用继承就不合适了,因为每次改变类之间关系都需要修改程序。这是,我们可以使用委托来代替继承关系。
上面代码的Display类中使用了委托. Display类的impl字段保存实现的实例,这样,类的任务就发生了转移

也就是说,当其他类要求Display类工作的时候,Display类并非自己工作,而是将工作交给impl。这就是委托。
继承是强关联关系,但委托是弱关联关系。这是因为只有Display类的实例生成时,才与作为参数被传入的类构成关联。例如:在实例程序中,当Main类生成Display类和CountDisplay类的实例时,才将StringDisplayImpl的实例作为参数传递给Display类和CountDisplay类
如果我们不传递StringDisplayImpl类的实例,而是将其他ConcreteImplementor角色的实例传递给Display类和CountDisplay类,就能很容易的改变实现。这时,发生变化的代码只有Main类,Display类和DisplayImpl类则不需要任务修改

(八)应用实例

jdbc 桥接模式

try {
            Class.forName("com.mysql.jdbc.Driver");
            String url="";
            String userName="";
            String password="";
            Connection conn = DriverManager.getConnection(url, userName, password);
            return conn;
        } catch (Exception e) {
            e.printStackTrace();
        }

这里就是用了设计模式中的桥接模式,我们知道不同的数据库自我实现和传输协议不同,java不可能为每种数据库厂商提供其实现,这不符合精简设计的原则,这里java提供了一套统一的接口让各个厂商自己实现,一套接口给程序开发者调用,两者的结合就是经典的桥接模式。
Jdbc 的 Driver接口,如果从桥接模式来看,Driver就是一个接口,下面可以有
MySQL的Driver,Oracle的Driver,这些就可以当做实现接口类

Mysql为例,通过Class.forName(“com.mysql.jdbc.Driver”)类加载的时候执行静态代码块将Driver注册到DriverManager,DriverManager是个Driver容器,管理不同的Driver,这样具体的数据Driver实现就统一交给容器管理,客户端通过DriverManager执行验证连接,获取连接的操作。

 static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }

转载:https://blog.csdn.net/Octopus21/article/details/104714039
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场