设计模式之桥接模式

写在前面

本文看下桥接设计模式。

1:介绍

1.1:什么时候桥接设计模式

当一个业务场景由多个变化维度组成,并且这多个变化的维度到底有多少种情况是不确定,比如现在我们要为瑞幸咖啡写一个系统,很自然的,需要在系统中来表示咖啡,此时思考下,咖啡有哪些维度呢,当然首先是咖啡,这是确定的,但是以下的维度却是不确定的:

1:杯子的大小,可能是大杯,中杯,小杯
2:咖啡的味道,可能是原味,加糖,加奶,加糖和奶

对于以上的这个场景,我们就可以考虑使用桥接设计模式来实现。

1.2:UML类图

原型设计模式,包含如下元素:

1:抽象化(Abstraction)角色
    使用多个变化维度中一个来定义,一个定义一个抽象类
2:修正抽象化(RefinedAbstraction)角色
    继承抽象化角色,增加额外的操作,如无特殊需求,可不需要(我理解的)
3:实现化(Implementor)角色
    多个变化维度的一个
4:具体实现化角色
    实现化角色子类,提供某个变化维度的具体变化类型

UML图如下:

设计模式之桥接模式_第1张图片

2:实例

源码 。

2.1:场景

现在有一个接口有一个方法需要一个List的参数,但是客户端只能提供逗号分割的字符串作为参数,这样就可以定义一个接受逗号分割的字符串参数的接口,并提供实现进行适配。

2.2:程序

比如现在我们要为瑞幸咖啡写一个系统,很自然的,需要在系统中来表示咖啡,此时思考下,咖啡有哪些维度呢,当然首先是咖啡,这是确定的,但是以下的维度却是不确定的:

1:杯子的大小,可能是大杯,中杯,小杯
2:咖啡的味道,可能是原味,加糖,加奶,加糖和奶

这里我们将杯子的大小来作为抽象化角色。

  • 定义实现化角色
    定义了往咖啡中加什么调料。
// 咖啡中加糖,牛奶,等的抽象接口(实现化的顶层接口)
// 抽象的是在咖啡中加什么东西(糖,牛奶,等)
public interface ICoffeeAdditives {
    void addSomething();
}
  • 定义具体实现化角色
    这里分别实现加奶和加糖,其它的需要的类比添加接口。
// 加奶(最终会加到咖啡中,生成加奶咖啡)
public class Milk implements ICoffeeAdditives {
    @Override
    public void addSomething() {
        System.out.println("加奶");
    }
}

//加糖
public class Sugar implements ICoffeeAdditives {
    @Override
    public void addSomething() {
        System.out.println("加糖");
    }
}
  • 定义抽象化角色
// 抽象化Abstraction
// 抽象是咖啡杯(大杯,小杯,中杯等)
public abstract class Coffee {
    // 保存一个实现话的引用,从而确定另外一个变化维度的信息
    protected ICoffeeAdditives additives;

    // 这里就好像桥一样,将抽象化和实现化连接在了一起,也正是桥接设计模式名称的来源
    public Coffee(ICoffeeAdditives additives){
        this.additives=additives;
    }

    // 客户点咖啡方法的抽象
    public abstract void orderCoffee(int count);
}

以上在构造函数中获取往咖啡加调料的类,就好像是一个桥一样,将杯子大小和咖啡加的调料建立了联系,这也是桥接设计模式中的桥接名称的来源。

  • 定义修正抽象话角色

这里仅仅是为了学习的完整性,但并无实际作用。

// 修正抽象化角色,增加新的操作,个人认为该类可有可无,如果没有特殊的需求
// ,在桥接设计模式中也可以没有该类
public abstract class RefinedCoffee extends Coffee {
    public RefinedCoffee(ICoffeeAdditives additives) {
        super(additives);
    }

//    public void checkQuality() {
//        Random ran = new Random();
//        System.out.println(String.format("%s 添加%s", additives.getClass().getSimpleName(), ran.nextBoolean() ? "太多" : "正常"));
//    }
}
  • 定义被子大小维度的大杯和小杯
public class SmallCoffee extends RefinedCoffee {
    public SmallCoffee(ICoffeeAdditives coffeeAdditives) {
        super(coffeeAdditives);
    }
    @Override
    public void orderCoffee(int count) {
        // 点了几杯咖啡
        System.out.println("点了" + count + " 小杯咖啡!");
        // 加什么
        super.additives.addSomething();
    }
}

public class LargeCoffee extends RefinedCoffee {
    public LargeCoffee(ICoffeeAdditives coffeeAdditives) {
        super(coffeeAdditives);
    }
    @Override
    public void orderCoffee(int count) {
        // 点了几杯咖啡
        System.out.println("点了" + count + " 大杯咖啡!");
        // 加什么
        super.additives.addSomething();
    }
}
  • 测试
// 两大杯加奶
@Test
public void testCase1() {
    RefinedCoffee largeWithMilk = new LargeCoffee(new Milk());
    largeWithMilk.orderCoffee(2);
}

输出:

点了2 大杯咖啡!
加奶
// 8小杯加糖
@Test
public void testCase2() {
    SmallCoffee smallCoffee = new SmallCoffee(new Sugar());
    smallCoffee.orderCoffee(8);
}

输出:

点了8 小杯咖啡!
加糖

写在后面

参考文章列表

秒懂设计模式之桥接模式(Bridge Pattern) 。

你可能感兴趣的:(设计模式,设计模式,桥接模式)