设计模式——桥接模式

210 阅读2分钟

1. 桥接模式概述

桥接模式是用于把抽象化与实现化解耦,使得二者可以独立变化。
桥接模式通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。

(1) 适用情况

如果系统有多个角度的分类,每个角度都有不同的实现,就可以使用桥接模式。
比如手机除了可以分为翻盖手机、直板手机等,还可以分为全面屏、曲面屏等,每个手机还有自己的品牌,比如华为,苹果,小米等。

(2) 优点

抽象和实现分离,方便拓展。

(3) 缺点

增加系统的理解和设计难度。

2. 桥接模式实例

我们还是用造车来举例,之前我们制造了不同品牌的车,但是却没有给他们指定车漆的颜色,可以使用桥接模式来实现。

(1) 声明汽车接口和颜色接口

public interface Car {
    void declare();
}
public interface Color {
    String print();
}

(2) 实现具体的汽车类

public class Benz implements Car {
    private Color color;

    public Benz(Color color) {
        this.color = color;
    }

    @Override
    public void declare() {
        System.out.println("我是一辆喷" + color.print() + "的奔驰。");
    }
}
public class BMW implements Car {
    private Color color;

    public BMW(Color color) {
        this.color = color;
    }

    @Override
    public void declare() {
        System.out.println("我是一辆喷" + color.print() + "的宝马。");
    }
}
public class Audi implements Car {
    private Color color;

    public Audi(Color color) {
        this.color = color;
    }

    @Override
    public void declare() {
        System.out.println("我是一辆喷" + color.print() + "的奥迪。");
    }
}

(3) 实现具体的颜色类

public class Red implements Color {
    @Override
    public String print() {
        return "红漆";
    }
}
public class Yellow implements Color {
    @Override
    public String print() {
        return "黄漆";
    }
}
public class Blue implements Color {
    @Override
    public String print() {
        return "蓝漆";
    }
}

(4) 生成喷不同颜色漆的不同品牌车

public class BridgeDemo {
    public static void main(String[] args) {
        Benz benz = new Benz(new Red());
        benz.declare();

        BMW bmw = new BMW(new Blue());
        bmw.declare();

        Audi audi = new Audi(new Yellow());
        audi.declare();
    }
}

运行结果:

image.png

3. 一些思考

桥接模式更好的体现了面向抽象/接口编程的理念,比如我们经常用到的用来记录日志的log4j和slf4j。
当我们需要在Maven项目中使用日志功能时,我们可以在pom.xml中做如下配置:

<!-- slf4j核心包 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>${slf4j.version}</version>
</dependency>

<!-- log4j2核心包 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>${log4j.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>${log4j.version}</version>
</dependency>

<!-- 用于与slf4j保持桥接 -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>${log4j.version}</version>
</dependency>

<!-- 引入lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>${lombok.version}</version>
</dependency>

实际上,slf4j是一个日志框架,它是对所有日志框架制定的一种规范、标准、接口,并不是一个框架的具体的实现,因为接口并不能独立使用,它需要和具体的日志框架来配合使用。
Log4j2是一个日志实现,它是一种记录日志的具体实现;
框架和实现的这种搭配使用方式,是为了以后如果项目对日志有其它要求而需要更换日志框架时可以不改动代码,只需要把依赖的jar包换掉就可以了。