今天是:
带着程序的旅程,每一行代码都是你前进的一步,每个错误都是你成长的机会,最终,你将抵达你的目的地。
title

桥接设计模式(Bridge Pattern)

定义

桥接模式(Bridge Pattern)是一种结构型设计模式,它用于将抽象部分与实现部分分离,以便它们可以独立地变化。桥接模式的核心思想是分离抽象和实现,使它们可以独立演化。这个模式将系统的抽象部分和实现部分分为两个独立的继承层次结构,从而降低了它们之间的耦合性。

意图

  • 分离抽象与实现:桥接模式的核心目标是分离抽象部分(抽象类或接口)与实现部分(具体实现类)以降低二者之间的耦合。这使得抽象和实现可以独立变化,不会相互影响。

  • 独立的变化:桥接模式允许抽象部分和实现部分独立演化。当需要引入新的抽象部分或实现部分时,不必修改已有的代码,这提高了系统的灵活性和可维护性。

  • 组合优于继承:桥接模式强调"组合优于继承"的设计原则。它避免了类层次结构的爆炸,通过将多个维度的变化分离,将类之间的关系简化为关联关系。

  • 多态性:桥接模式允许在运行时动态地选择不同的实现,从而实现多态性。这有助于实现不同组合下的多样性行为。

  • 增加灵活性和可扩展性:桥接模式增加了系统的灵活性,允许更容易地适应变化。当需求发生变化时,可以轻松地添加新的抽象或实现。

参与者

  • 抽象部分(Abstraction):定义了抽象部分的接口,通常包含一些高级操作,它内部包含对实现部分的引用。抽象部分可以是一个抽象类或接口。

  • 扩展抽象部分(Refined Abstraction):继承自抽象部分,扩展了抽象部分的接口,并可以包含一些具体的业务逻辑。

  • 实现部分(Implementor):定义实现部分的接口,通常也是一个抽象类或接口。

  • 具体实现部分(Concrete Implementor):实现实现部分的接口,提供具体的功能。

举例

某公司为庆周年庆,向客户发送一批优惠券,优惠券有不同的类型和金额,那么显然创建所有类型所有金额的优惠券显然是不现实的,这里使用桥接模式

类图:

java bridge design pattern

这个例子中对应类的角色如下:

  • 抽象化(Abstraction)Coupon 接口就是抽象化角色,它定义了基于 DiscountType 的 applyCoupon 方法。

  • 扩充抽象化(Refined Abstraction)FixedAmountCoupon 和 PercentageCoupon 类就是扩充抽象化角色,它们是 Coupon 接口的具体实现。

  • 实现化(Implementor)DiscountType 接口就是实现化角色,它定义了 applyDiscount 方法。

  • 具体实现化(Concrete Implementor)AmountDiscountFixedDiscount 和 TieredDiscount 类就是具体实现化角色,它们是 DiscountType 接口的具体实现。

在这个例子中,Coupon 和 DiscountType 之间的桥接使得 Coupon 可以独立于 DiscountType 变化,也就是说,你可以自由地添加新的 Coupon 类型和 DiscountType 类型,而不需要修改现有的代码。

 

Coupon

public interface Coupon {
    void applyCoupon(double amount);
}

 

固定数量优惠券

public class FixedAmountCoupon implements Coupon {
    private DiscountType discountType;
    private double fixedAmount;

    public FixedAmountCoupon(DiscountType discountType, double fixedAmount) {
        this.discountType = discountType;
        this.fixedAmount = fixedAmount;
    }

    @Override
    public void applyCoupon(double amount) {
        discountType.applyDiscount(amount - fixedAmount);
    }
}

 

折扣优惠券

public class PercentageCoupon implements Coupon {
    private DiscountType discountType;
    private double percentage;

    public PercentageCoupon(DiscountType discountType, double percentage) {
        this.discountType = discountType;
        this.percentage = percentage;
    }

    @Override
    public void applyCoupon(double amount) {
        discountType.applyDiscount(amount * (1 - percentage));
    }
}

 

折扣类型

public interface DiscountType {
    void applyDiscount(double amount);
}

 

不同的折扣实现类

@Slf4j
// 固定金额的优惠额
public class AmountDiscount implements DiscountType {
    @Override
    public void applyDiscount(double amount) {
        log.info("应付金额: " + amount);
    }
}


@Slf4j
//根据购物金额的折扣
public class TieredDiscount implements DiscountType {
    @Override
    public void applyDiscount(double amount) {
        double discount;
        if (amount < 100) {
            discount = 0.05;
        } else if (amount < 200) {
            discount = 0.1;
        } else {
            discount = 0.15;
        }
        log.info("应付金额: " + (amount * (1 - discount)));
    }
}

 

测试

@Slf4j
public abstract class App implements DiscountType {
    public static void main(String[] args) {
        DiscountType discountType = new AmountDiscount();
        DiscountType tieredType = new TieredDiscount();
        Coupon fixedAmountCoupon = new FixedAmountCoupon(discountType, 10);
        Coupon percentageCoupon = new PercentageCoupon(discountType, 0.25);
        Coupon tieredPercentageCoupon = new PercentageCoupon(tieredType, 0.1);

        log.info("固定金额优惠券:");
        fixedAmountCoupon.applyCoupon(100);

        log.info("百分比优惠券:");
        percentageCoupon.applyCoupon(100);

        //折上折
        log.info("根据金额计算折扣优惠券:");
        tieredPercentageCoupon.applyCoupon(100);
    }
}

 

运行结果

 

优点

  1. 分离抽象与实现:桥接模式将抽象部分与实现部分分离,使它们可以独立变化。这有助于降低类之间的耦合,使系统更加灵活,允许它们独立演化。

  2. 可扩展性:由于桥接模式允许添加新的抽象部分和新的实现部分,它提供了很好的扩展性。您可以轻松地引入新的维度,而不需要修改现有的代码。

  3. 多态性:桥接模式允许在运行时动态地选择实现,从而实现多态性。这有助于实现不同组合下的多样性行为。

  4. 避免类爆炸问题:在某些情况下,如果不使用桥接模式,可能需要大量的子类,导致类的爆炸问题。桥接模式可以减少子类的数量,使代码更可管理。

  5. 分离接口和实现:桥接模式有助于分离接口和实现,这样接口不会受到实现的影响,实现也不会受到接口的影响。这使得修改接口或实现变得更加容易。

  6. 复用性:由于桥接模式的分离性,可以更容易地重用抽象部分和实现部分,减少代码冗余。

  7. 适应性:桥接模式使系统更容易适应变化。当需求发生变化时,您可以轻松地添加新的抽象或实现,而不会破坏现有的结构。

缺点

  1. 复杂性增加:引入桥接模式会增加代码的复杂性,因为它需要创建多个抽象和具体类,这可能会增加项目的代码量。

  2. 抽象和实现的分离:虽然抽象和实现的分离有助于灵活性,但也可能导致代码的分散和可读性降低。程序员需要明确了解抽象和实现之间的关系,以避免混淆。

  3. 设计复杂性:当只有一个维度的变化时,使用桥接模式可能会显得过于复杂。在这种情况下,桥接模式可能会引入不必要的复杂性,增加代码维护成本。

  4. 性能开销:在某些情况下,桥接模式可能引入性能开销,因为需要通过抽象部分调用实现部分,可能导致额外的方法调用和开销。

  5. 适用性:桥接模式通常更适用于那些有多个维度需要独立变化的情况。如果系统只有一个维度的变化,引入桥接模式可能是过度工程。

 

Spring JdbcTemplate中桥接模式的使用

Slf4j日志中桥接模式的应用

分享到:

专栏

类型标签

网站访问总量