设计模式之Bridge模式(桥接模式)

这几天重新去看spring系列的框架了(也又次体会到了理解设计模式在学习框架时的好处),没有接着写,发生了一些事,又少了些许束缚,但结果对向往自由的我来说总是好的,虎入山林,龙归沧海,听听音乐,整理整理博客。

书上的介绍比较简单,抽象,又看了一些其他东西才理解了一些。首先来介绍一下类的两个层次结构:功能层次结构和实现层次结构。
所谓功能层次结构,我们现在有一个类ActionSomething,想在它上面拓展新的功能,直接的方法就是继承他,添加一个派生类ActionSomethingGood,如果再想拓展功能会继续继承ActionSomethingGood,接着派生出ActionSomethingBetter,这样就是一个三层的功能层次结构,不过通常来说,类的层次结构不应过深。
设计模式之Bridge模式(桥接模式)_第1张图片
然后是实现层次结构,模板方法模式中,我们了解了抽象类的强大之处,父类不但对子类规定了要实现的接口,还强制约束了这些接口的工作流程。父类的任务就是定义接口,而子类的任务就是实现这些抽象方法,这也是一种层次结构。例如,子类ConcreteClass实现了父类AbstractClass的抽象方法,构成了一个两层的实现结构:
设计模式之Bridge模式(桥接模式)_第2张图片
但这个地方并非用来新增功能,而是为了实现新的任务分组,这就是类的实现层次结构,如果之后要以其他方式实现AbstractClass,只需再继承并实现类AnotherConcreteClass,类的层次结构发生了点变化:
设计模式之Bridge模式(桥接模式)_第3张图片
我个人的简单理解就是功能层次结构就意味着功能的增加,而实现层次结构意味着功能的修改。
接下来是重点,也是桥接模式的主要优点:分离类的功能层次结构和实现层次结构。当然,如果只是简单的分离,两者之间必然缺少某种联系,因此还需要在二者之间搭起一个桥梁。书上说Bridge模式的作用就是搭建这座桥梁,但我个人的理解是如何分离类的两个层次结构也许更加重要。

说了不少,大伙可能还没理解,还是看一些代码更加容易理解,书上的例子我感觉可能还是有点抽象,因此我来写一个从别的地方看到的例子。
假如现在有一个生产各种笔的工厂,一开始规模较小,只生产铅笔和钢笔,笔的功能比较少,只有书写的功能,但不同笔在书写之前要做的操作是不一样的,我们可以得到以下的设计:
首先是一个抽象的笔类(此处使用了一点模板方法模式):

/**
 * @author lenovo
 * @title: AbstractPen
 * @projectName LearnDesignMode
 * @description: 抽象笔类
 * @date 2022/5/1523:18
 */
public abstract class AbstractPen {
    //笔在写之前要进行的操作  不同笔不一样,铅笔,钢笔等
    abstract void beforePrint();

    public void printSomething(String context) {
        beforePrint();
        System.out.println("写了" + context);
    }
}

接着我们来看铅笔和钢笔的实现类:

public class Pencil extends AbstractPen {
    @Override
    void beforePrint() {
        System.out.println("铅笔使用铅笔刀削好了");
    }
}
public class Pen extends AbstractPen {
    @Override
    void beforePrint() {
        System.out.println("钢笔拔下了笔帽,吸足了墨水");
    }
}

使用Main方法测试一下:

public class Main {
    public static void main(String[] args) {

        AbstractPen pen = new Pen();
        AbstractPen pencil = new Pencil();

        String context = "Hello,World";

        pen.printSomething(context);
        pencil.printSomething(context);
    }
}

输出结果:

钢笔拔下了笔帽,吸足了墨水
写了Hello,World
铅笔使用铅笔刀削好了
写了Hello,World

现在来看万事大吉,工厂在不断生产出笔来获取利润,慢慢的工厂做大,为卖出更多的笔,赚取更多利润,老板不再满足他的笔只有书写的功能,开始增加花里胡哨的功能,我们大可以直接由铅笔类和钢笔类进行派生进而增加新的功能,也遵守了开闭原则:

public class GoodPencil extends Pencil{
    public void newAbility() {
        System.out.println("第一个花里胡哨的功能");
    }
}
public class GoodPen extends Pen {
    public void newAbility() {
        System.out.println("第一个花里胡哨的功能");
    }
}

使用Main测试下:

public class Main {
    public static void main(String[] args) {

        GoodPen pen = new GoodPen();

        GoodPencil pencil = new GoodPencil();

        String context = "Hello,World";

        pen.printSomething(context);
        pen.newAbility();

        pencil.printSomething(context);
        pencil.newAbility();
    }
}

输出结果:

钢笔拔下了笔帽,吸足了墨水
写了Hello,World
第一个花里胡哨的功能
铅笔使用铅笔刀削好了
写了Hello,World
第一个花里胡哨的功能

好的,新增两个类之后,新的功能增加了,也没有破坏设计程序的开闭原则,看起来我们之前的设计好像是没有问题,有新的功能拓展起来非常棒。但老板仍不满足现状,又决定开始制造中性笔,新增一个中性笔类:

public class RollerBallPen extends AbstractPen {
    @Override
    void beforePrint() {
        System.out.println("中性笔拔下了笔帽");
    }

    public void newAbility() {
        System.out.println("第一个花里胡哨的功能");
    }
}

测试下并输出:

public class Main {
    public static void main(String[] args) {
        String context = "Hello,World";

        RollerBallPen rollerBallPen = new RollerBallPen();
        rollerBallPen.printSomething(context);
        rollerBallPen.newAbility();
    }
}
中性笔拔下了笔帽
写了Hello,World
第一个花里胡哨的功能

结果还不错,因为新增了一种笔,我们新增了一个类,还是达到了要求,但隐约感觉好像开始有问题了。果然,人的贪欲是无止境的。第二天,老板又要给所有的笔增加第二个花里胡哨的新功能。现在我们要怎么做,接着派生之前的三个类,增加新功能吗,类似下面的处理:

public class BetterPencil extends GoodPencil {
    public void secondNewAbility() {
        System.out.println("第二个花里胡哨的功能");
    }
}

要求肯定是可以达到的,可就因为一个小小功能的增加,我们要再增加三个类似的类来完成,如果后面再有新的笔呢,再来个马克笔,毛笔,水彩笔等等,到那时我们如果再新增一个新的功能会怎么样呢,类的个数是指数式增长的,想想就很恐怖。
造成如此的原因是什么,就是因为每种笔在使用之前的处理不同,这就是类的实现层次结构,新功能的添加呢,不就是类的功能层次结构吗,我们正可以通过桥接模式对这两种结构进行分离,来看改变之后的代码:
首先是AbstractPen,他不再是一个抽象类(主要因为在此处已没有要被子类实现的功能),并把之前的笔在使用之前的方法封装在了接口PenHandle中,在AbstractPen中引入即可:

public class AbstractPen {

    private PenHandle penHandle;

    public AbstractPen(PenHandle penHandle) {
        this.penHandle = penHandle;
    }

    public void printSomething(String context) {
        penHandle.beforePrint();
        System.out.println("写了" + context);
    }
}
public interface PenHandle {
    //使用前要进行的操作
    void beforePrint();
}

现在我们来实现三种笔的预处理:

public class PencilHandleImpl implements PenHandle {
    @Override
    public void beforePrint() {
        System.out.println("铅笔使用铅笔刀削好了");
    }
}
public class PenHandleImpl implements PenHandle {
    @Override
    public void beforePrint() {
        System.out.println("钢笔拔下了笔帽,吸足了墨水");
    }
}
public class RollerBallPenHandleImpl implements PenHandle {
    @Override
    public void beforePrint() {
        System.out.println("中性笔拔下了笔帽");
    }
}

那要如何生产三种笔呢,直接看Main方法:

public class Main {
    public static void main(String[] args) {

        String context = "Hello,World";

        PenHandle pen = new PenHandleImpl();
        PenHandle pencil = new PencilHandleImpl();
        PenHandle rollerBallPen = new RollerBallPenHandleImpl();

        AbstractPen concretePen = new AbstractPen(pen);
        AbstractPen concretePencil = new AbstractPen(pencil);
        AbstractPen concreteRollerBallPen = new AbstractPen(rollerBallPen);

        concretePen.printSomething(context);
        concretePencil.printSomething(context);
        concreteRollerBallPen.printSomething(context);

    }
}

来看结果:

钢笔拔下了笔帽,吸足了墨水
写了Hello,World
铅笔使用铅笔刀削好了
写了Hello,World
中性笔拔下了笔帽
写了Hello,World

非常好的完成了任务,那要新增功能呢,只需继承AbstractPen并拓展即可:

public class GoodPen extends AbstractPen {
    public GoodPen(PenHandle penHandle) {
        super(penHandle);
    }

    public void newAbility() {
        System.out.println("第一个花里胡哨的功能");
    }
}

测试一下并输出:

public class Main {
    public static void main(String[] args) {

        String context = "Hello,World";

        PenHandle pen = new PenHandleImpl();
        PenHandle pencil = new PencilHandleImpl();
        PenHandle rollerBallPen = new RollerBallPenHandleImpl();

        GoodPen concretePen = new GoodPen(pen);
        GoodPen concretePencil = new GoodPen(pencil);
        GoodPen concreteRollerBallPen = new GoodPen(rollerBallPen);

        concretePen.printSomething(context);
        concretePen.newAbility();
        concretePencil.printSomething(context);
        concretePencil.newAbility();
        concreteRollerBallPen.printSomething(context);
        concreteRollerBallPen.newAbility();

    }
}
钢笔拔下了笔帽,吸足了墨水
写了Hello,World
第一个花里胡哨的功能
铅笔使用铅笔刀削好了
写了Hello,World
第一个花里胡哨的功能
中性笔拔下了笔帽
写了Hello,World
第一个花里胡哨的功能

如果还有新的功能呢,依旧是继承,然后派生即可,而不是有多少种笔就新增多少类,那是非常糟糕的处理。
此时我们就实现了类的功能层次结构(新增功能)和实现层次结构(修改功能)的分离,以上我个人对桥接模式的一些理解。

这篇文章可以说是我写的比较认真的,写的时间也比较长,希望看到这里的各位点赞支持一下,大家一起进步。

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