设计模式之桥接模式

桥接模式

桥接模式

桥接模式(Bridge Pattern)也称为桥梁模式、接口(Interfce)模式或柄体(Handle and Body)模式,是将抽象部分与它的具体实现部分分离,使它们都可以独立地变化,属于结构型模式。

解释:解耦抽象和实现,使得两者可以独立的变化。

桥接模式主要目的是通过组合的方式建立两个类之间的联系,而不是继承。但又类似于多重继承方案,但是多重继承方案往往违背了类的单一职责原则,其复用性比较差,桥接模式是比多重继承更好的替代方案,桥接模式的核心在于解耦抽象和实现。

注:此处的抽象并不是指抽象类或接口这种高层概念,实现也不是继承或接口实现。抽象与实现其实指的是两种独立变化的维度。其中,抽象包含实现,因此,一个抽象类的变化可能涉及到多种维度的变化导致的

UML图如下

image-20210421234355429

桥接模式主要包含四种角色

抽象(Abstraction):该类持有一个对实现角色的引用,抽象角色中的方法需要实现角色来实现。抽象角色一般为抽象类(构造函数规定子类要传入一个实现对象);

修正抽象(RefinedAbstraction):Abstraction的具体实现,对Abstraction的方法进行完善和扩展;

实现(Implementor):确定实现维度的基本操作,提供给Abstraction使用。该类一般为接口或抽象类;

具体实现(Concretelmplementor):Impementor的具体实现。

桥接模式的通用写法

创建实现角色Implementor类:

1
2
3
4
public interface Implementor
{
void operation();
}

创建抽象角色Abstraction类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public abstract class Abstraction
{

private Implementor implementor;

public Abstraction(Implementor implementor)
{
this.implementor = implementor;
}

public void operation()
{
implementor.operation();
}
}

创建修正抽象角色RefinedAbstraction类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class RefinedAbstraction extends Abstraction
{
public RefinedAbstraction(Implementor implementor)
{
super(implementor);
}

@Override
public void operation()
{
super.operation();
System.out.println("refined operation");
}
}

创建具体实现ConcretelmplementorA类:

1
2
3
4
5
6
7
8
public class ConcreteImplementorA implements Implementor
{
@Override
public void operation()
{
System.out.println("ConcreteImplementorA");
}
}

测试代码

1
2
3
4
5
6
7
8
9
public class Main
{
public static void main(String[] args)
{
ConcreteImplementorA concreteImplementorA = new ConcreteImplementorA();
Abstraction abstraction = new RefinedAbstraction(concreteImplementorA);
abstraction.operation();
}
}

输出

1
2
ConcreteImplementorA
refined operation

桥接模式的应用场景

当一个类内部具备两种或多种变化维度时,使用桥接模式可以解耦这些变化的维度,使高层代码架构稳定。

桥接模式适用于以下几种业务场景:

1、在抽象和具体实现之间需要增加更多的灵活性的场景。

2、一个类存在两个(或多个)独立变化的维度,而这两个(或多个)维度都需要独立进行扩展。

3、不希望使用继承,或因为多层继承导致系统类的个数剧增。

注:桥接模式的一个常用使用场景就是为了替换继承。继承拥有很多优点,比如抽象,封装,多态等,父类封装共性,子类实现特性。继承可以很好地帮助我们实现代码复用(封装)的功能,但是同时,这也是继承的一大缺点。因为父类拥有的方法,子类也会继承得到,无论子类需不需要,这说明了继承具备强侵入性(父类代码侵入子类),同时会导致子类臃肿….因此,在设计模式中,有一个原则为:优先使用组合/聚合的方式,而不是继承。

桥接模式在源码中的应用

大家非常熟悉的JDBCAPI,其中有一个Driver类就是桥接对象。我们都知道,我们在使用的时候通过Class.forName(方法可以动态加载各个数据库厂商实现的Driver类。

具体客户端应用代码如下,以MySQL的实现为例:

1
2
3
4
5
6
7
8
9
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");//反射机制加载驱动类
//2.获取连接Connection
//主机:端口号/微据库名
connection conn= DriverManager.getconnection("jdbc:mysql://localhost:33e6/test","root","root");
//3.得到执行sql语句的对象Statement
statement stmt = conn.createstatement();
//4.执行sql语句,并返回结果
Resultset rs = stmt.executeQuery("select *from table");

Driver在JDBC中并没有做任何实现,具体的功能实现由各厂商完成,我们以MySQL的实现为例。

1
2
3
4
5
6
7
8
9
10
11
12
public class Driver extends NonRegisteringpriver implements java.sql.Driver {
public Driver() throws sQLexception {
}
static
{
try{
DriverManager.registeroriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}

当执行Class.forName("com.myqljdbc.Driver")方法的时候,就会执行com.mysql.jdbc.Driver这个类的静态块中的代码。而静态块中的代码只是调用了一下DriverManager的registerDriver()方法然后将Driver对象注册到DriverManager中,DriverManager就是桥,连接各个数据库厂商的具体实现。

桥接模式的优缺点

桥接模式遵循了里氏替换原则和依赖倒置原则,最终实现了开闭原则,对修改关闭,对扩展开放。

这里将桥接模式的优缺点总结如下

优点:

1、分离抽象部分及其具体实现部分

2、提高了系统的扩展性

3、符合开闭原则

4、符合合成复用原则

缺点:

1、增加了系统的理解与设计难度

2、需要正确地识别系统中两个独立变化的维度

打赏

请我喝杯咖啡吧~

支付宝
微信