博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
经典设计模式——桥接模式
阅读量:5941 次
发布时间:2019-06-19

本文共 3087 字,大约阅读时间需要 10 分钟。

  hot3.png

    桥接模式是一种结构型模式,它主要应对的是:由于实际的需要,某个类具有两个或以上维度的变化,如果只是使用继承,将无法实现这种需要,或者是的设计变得更加臃肿。

    举例来说,假设现在我们需要为某个餐厅制造菜单,餐厅供应牛肉面、猪肉面……,而且顾客可以根据自己的口味选择是否添加辣椒。此时就产生了一个问题,我们如何来应对这种变化(这已经是两个维度的变化了,一个维度是面里面加的什么肉,另一个维度是加不加辣椒)?我们是否需要定义辣椒牛肉面、无辣牛肉面、辣椒猪肉面、无辣猪肉面4(2^2)个子类?如果还有一个加不加醋的面呢(这是第三个维度)?那不是要定义8(2^3)个子类?想想如果餐厅还供应羊肉面,酸菜面呢?

    为了解决这个问题,我们可以使用桥接模式,桥接模式的做法是把变化的部分抽象出来,使变化部分与主类(相当于就是桥接类)分离开来,从而将多个维度的变化彻底分离。最后提供一个管理类来组合不同维度上的变化,通过这种组合来满足业务需要。

    下面以一个简单的实例来说明桥接模式的使用。程序先提供了一个Peppery接口,该接口代表是否添加辣椒:

public interface Peppery {    String style();}

    接着为该接口提供两个实现类,它们分别表示添加辣椒和不添加辣椒:

public class PepperyStyle implements Peppery {    @Override    public String style() {        System.out.println("辣味十足,爽!");    }}

public class PlainStyle implements Peppery {    @Override    public String style() {        System.out.println("清淡一点,养胃");    }}

    从上面的接口可以看出,Peppery接口代表了加不加辣椒这个维度的变化,不论面条在该维度上有多少种变化(辣味还可能有微辣、中辣、重辣等),程序只需要为这几种变化分别提供实现类即可。对于系统而言,辣味风格这个维度上的变化是固定的,程序必须面对的 ,程序使用桥接模式将辣味风格这个维度的变化抽象出来,避免了与牛肉、猪肉、羊肉等材料这个维度的变化耦合在一起。

    接着程序提供了一个AbstractNoodle抽象类,该抽象类将会持有一个Peppery属性,该属性代表面条的辣味风格。程序通过AbstractNoodle组合一个Peppery对象,从而实现了面条在辣味风格这个维度上的变化,而AbstractNoodle本身可以包含很多实现类,不同实现类则代表了面条在不同材料风格这个维度的变化。下面是AbstractNoodle的代码:

public abstract class AbstractNoodle {    protected Peppery style;    public AbstractNoodle(Peppery style) {        this.style = style;    }    public abstract void eat();}

    正如上面的代码所示,AbstractNoodle类中持有一个Peppery类型的实例,不同的AbstractNoodle实例与不同的Pepper实例组合,就可以完成辣味风格、材料风格两个维度的变化(这里只简单说明这两个维度的变化,更多维度,原理相同)。由此可见,AbstractNoodle抽象类可以看作是一个桥梁,它被用来“桥接”面条的材料风格的改变与辣味风格的改变,是面条的特殊属性得到无绑定的扩充。

    接下类为AbstractNoodle提供一个子类PorkyNoodle,该类代表了“猪肉面”:

public class PorkyNoodle extends AbstractNoodle {    public PorkyNoodle(Peppery style) {        super(style)    }    @Override    public void eat() {        System.out.println("这是一碗猪肉面,辣味风格为:" + super.style.style());    }}

    再提供一个BeefNoodle,该子类代表了“牛肉面”:

public class BeefNoodle extends AbstractNoodle {    public BeefNoodle(Peppery style) {        super(style)    }    @Override    public void eat() {        System.out.println("这是一碗牛肉面,辣味风格为:" + super.style.style());    }}

    从PorkyNoodle和BeefNoodle中可以看出,AbstractNoodle的两个具体类实现eat()方法时,既组合了材料风格的变化,也组合了辣味风格的变化,从而可以表现出两个维度的变化。桥接模式下,这些接口和类之间的结构关系如下:

213809_3Btl_1434710.jpg

    下面提供一个主程序,可以分别产生辣椒牛肉面、无辣牛肉面、辣椒猪肉面、无辣猪肉面等几种风格的面条:

public class Test {    public static void main(String args[]) {        //辣椒牛肉面        AbstractNoodle noodle1 = new BeefNoodle(new PepperyStyle());        //无辣牛肉面        AbstractNoodle noodle2 = new BeefNoodle(new PlainStyle());        //辣椒猪肉面        AbstractNoodle noodle3 = new PorkyNoodle(new PepperyStyle());        //无辣猪肉面        AbstractNoodle noodle4 = new PorkyNoodle(new PlainStyle());                noodle1.eat();        noodle2.eat();        noodle3.eat();        noodle4.eat();    }}

    上面的main方法中得到了这4中面条,这4种面条满足了面条在两个维度上的变化,而程序结构又足够清晰且扩展性好。

    桥接模式在JavaEE架构中有非常广泛的用途,由于JavaEE应用需要实现跨数据库的功能,程序为了在不同数据库之间迁移,因此系统需要在持久化技术这个维度上存在改变;除此之外,系统也需要在不同业务逻辑实现之间迁移,因此也需要在逻辑实现这个维度存在改变,这正好符合桥接模式的使用场景。因此,JavaEE应用都会推荐使用业务逻辑组件和DAO组件分离的结构,让DAO组件负责持久化技术这个维度上的改变,让业务逻辑组件负责业务逻辑实现这个维度上的改变。由此可见,JavaEE应用中常见的DAO模式正是桥接模式的应用。

转载于:https://my.oschina.net/itblog/blog/215221

你可能感兴趣的文章
ios 打包上传Appstore 时报的错误 90101 90149
查看>>
Oracle推出轻量级Java微服务框架Helidon
查看>>
密码概述
查看>>
autoconf,automake,libtool
查看>>
jQuery的技巧01
查看>>
基于泛型实现的ibatis通用分页查询
查看>>
gopacket 使用
查看>>
AlertDialog对话框
查看>>
我的友情链接
查看>>
linux安全---cacti+ntop监控
查看>>
鸟哥的linux私房菜-shell简单学习-1
查看>>
nagios配置监控的一些思路和工作流程
查看>>
通讯组基本管理任务三
查看>>
赫夫曼编码实现
查看>>
html页面显示div源代码
查看>>
基础复习-算法设计基础 | 复杂度计算
查看>>
debian、ubuntu系统下,常用的下载工具
查看>>
带以太网的MicroPython开发板:TPYBoardv201温湿度上传实例
查看>>
如何解压缩后缀名为zip.001,zip.002等的文件
查看>>
OSGI企业应用开发(十二)OSGI Web应用开发(一)
查看>>