设计模式(八)桥接模式

1、概述

桥接模式是一种结构型设计模式, 可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构, 从而能在开发时分别使用。

2、适用场景

1)如果你想要拆分或重组一个具有多重功能的庞杂类 , 可以使用桥接模式。
2) 如果你希望在几个独立维度上扩展一个类, 可使用该模式。对象的属性有其他类去实现,不需要自己处理所有工作。
3)如果你需要在运行时切换不同实现方法, 可使用桥接模式。桥接模式可替换抽象部分中的实现对象, 具体操作就和给成员变量赋新值一样简单。

3、实例

有以下场景:

支付途径:微信,支付宝
支付方式:指纹,扫脸

3.1 不使用桥接模式

定义两个枚举

/**
 * 支付方式
 * @date: 2021/1/7
 * @author weirx
 * @version 3.0
 */
public enum PayMethodEnum {

    FACE(0, "扫脸"),
    FINGER(1, "指纹");


    PayMethodEnum(int code, String name) {
        this.code = code;
        this.name = name;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getName(int code) {
        PayMethodEnum[] payWaysEnums = values();
        for (PayMethodEnum payMethodEnum : payWaysEnums) {
            if (payMethodEnum.code == code) {
                return payMethodEnum.name;
            }
        }
        return null;
    }

    public void setName(String name) {
        this.name = name;
    }

    private int code;

    private String name;

}
/**
 * 支付方式
 * @date: 2021/1/7
 * @author weirx
 * @version 3.0
 */
public enum PayWaysEnum {

    ZHIFUBAO(0, "支付宝"),
    WEIXIN(1, "微信");


    PayWaysEnum(int code, String name) {
        this.code = code;
        this.name = name;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    private int code;


    public void setName(String name) {
        this.name = name;
    }

    public String getName(int code) {
        PayWaysEnum[] payWaysEnums = values();
        for (PayWaysEnum payWaysEnum : payWaysEnums) {
            if (payWaysEnum.code == code) {
                return payWaysEnum.name;
            }
        }
        return null;
    }

    private String name;

}

定义支付业务流程:

/**
 * TODO
 * @date: 2021/1/7
 * @author weirx
 * @version 3.0
 */
public class Pay {

    public void pay(int payMethod, int payWay) {
        if (PayMethodEnum.FACE.getCode() == payMethod) {
            System.out.println("当前支付方式是:" + PayMethodEnum.FACE.getName(payMethod));
        } else {
            System.out.println("当前支付方式是:" + PayMethodEnum.FINGER.getName(payMethod));
        }
        if (PayWaysEnum.ZHIFUBAO.getCode() == payWay) {
            System.out.println("当前支付途径是:" + PayWaysEnum.ZHIFUBAO.getName(payWay));
        } else {
            System.out.println("当前支付途径是:" + PayWaysEnum.WEIXIN.getName(payWay));
        }
    }
}

测试类:

/**
 * 客户端
 * @date: 2021/1/4
 * @author weirx
 * @version 3.0
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = BsspUserApplication.class)
public class TestDemo {

    @Test
    public void test() {
        Pay pay = new Pay();
        //支付宝扫脸支付
        pay.pay(PayMethodEnum.FACE.getCode(),PayWaysEnum.ZHIFUBAO.getCode());
        System.out.println("--------------------------------------");
        //微信扫脸支付
        pay.pay(PayMethodEnum.FACE.getCode(),PayWaysEnum.WEIXIN.getCode());
        System.out.println("--------------------------------------");
        //支付宝指纹支付
        pay.pay(PayMethodEnum.FINGER.getCode(),PayWaysEnum.ZHIFUBAO.getCode());
        System.out.println("--------------------------------------");
        //微信指纹支付
        pay.pay(PayMethodEnum.FINGER.getCode(),PayWaysEnum.WEIXIN.getCode());
        System.out.println("--------------------------------------");
    }

}

结果:

当前支付方式是:扫脸
当前支付途径是:支付宝
--------------------------------------
当前支付方式是:扫脸
当前支付途径是:微信
--------------------------------------
当前支付方式是:指纹
当前支付途径是:支付宝
--------------------------------------
当前支付方式是:指纹
当前支付途径是:微信
--------------------------------------

3.2 使用桥接模式

定义枚举:

package com.cloud.bssp.designpatterns.bridge.usedesign.enums;

/**
 * 支付方式
 * @date: 2021/1/7
 * @author weirx
 * @version 3.0
 */
public enum PayMethodEnum {

    FACE(0, "扫脸"),
    FINGER(1, "指纹");


    PayMethodEnum(int code, String name) {
        this.code = code;
        this.name = name;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private int code;

    private String name;

}
package com.cloud.bssp.designpatterns.bridge.usedesign.enums;

/**
 * 支付方式
 * @date: 2021/1/7
 * @author weirx
 * @version 3.0
 */
public enum PayWaysEnum {

    ZHIFUBAO(0, "支付宝"),
    WEIXIN(1, "微信");


    PayWaysEnum(int code, String name) {
        this.code = code;
        this.name = name;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    private int code;


    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    private String name;

}

定义两个顶层抽象接口:

/**
 * 支付接口
 * @date: 2021/1/7
 * @author weirx
 * @version 3.0
 */
public interface IPayMethod {

    void pay();
}
/**
 * 支付接口
 * @date: 2021/1/7
 * @author weirx
 * @version 3.0
 */
public interface IPayWay {

    void pay();
}

定义两种支付方式:

/**
 * 指纹
 * @date: 2021/1/7
 * @author weirx
 * @version 3.0
 */
public class FingerPay implements IPayMethod {

    @Override
    public void pay() {
        System.out.println("当前支付方式是:" + PayMethodEnum.FINGER.name());
    }
}
/**
 * 扫脸
 * @date: 2021/1/7
 * @author weirx
 * @version 3.0
 */
public class FacePay implements IPayMethod {

    @Override
    public void pay() {
        System.out.println("当前支付方式是:" + PayMethodEnum.FACE.name());
    }
}

定义两种支付途径:

/**
 * 微信
 * @date: 2021/1/7
 * @author weirx
 * @version 3.0
 */
public class WXPayWay implements IPayWay {

    private IPayMethod payMethod;

    public WXPayWay(IPayMethod payMethod) {
        this.payMethod = payMethod;
    }

    @Override
    public void pay() {
        System.out.println("当前支付方式是:" + PayWaysEnum.WEIXIN.getName());
        payMethod.pay();
    }
}
/**
 * 支付宝
 * @date: 2021/1/7
 * @author weirx
 * @version 3.0
 */
public class ZFBPayWay implements IPayWay {

    private IPayMethod payMethod;

    public ZFBPayWay(IPayMethod payMethod) {
        this.payMethod = payMethod;
    }

    @Override
    public void pay() {
        System.out.println("当前支付方式是:" + PayWaysEnum.ZHIFUBAO.getName());
        payMethod.pay();
    }
}

测试类:

/**
 * 客户端
 * @date: 2021/1/4
 * @author weirx
 * @version 3.0
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = BsspUserApplication.class)
public class TestDemo {

    @Test
    public void test() {
        FacePay facePay = new FacePay();
        FingerPay fingerPay = new FingerPay();
        ZFBPayWay zfbPayFace = new ZFBPayWay(facePay);
        WXPayWay wxPayWayFace = new WXPayWay(facePay);
        ZFBPayWay zfbPayFinger = new ZFBPayWay(fingerPay);
        WXPayWay wxPayWayFinger = new WXPayWay(fingerPay);
        //支付宝扫脸支付
        zfbPayFace.pay();
        System.out.println("--------------------------------------");
        //微信扫脸支付
        wxPayWayFace.pay();
        System.out.println("--------------------------------------");
        //支付宝指纹支付
        zfbPayFinger.pay();
        System.out.println("--------------------------------------");
        //微信指纹支付
        wxPayWayFinger.pay();
        System.out.println("--------------------------------------");
    }

}

结果:

当前支付方式是:支付宝
当前支付方式是:FACE
--------------------------------------
当前支付方式是:微信
当前支付方式是:FACE
--------------------------------------
当前支付方式是:支付宝
当前支付方式是:FINGER
--------------------------------------
当前支付方式是:微信
当前支付方式是:FINGER
--------------------------------------

4、分析

如上两种方式都实现了四种支付的过程,其中是以支付途径(支付宝、微信)为主,包含两种支付方式(扫脸、指纹)。

从代码量分析:
不使用:代码还是比较少的,但是其实主要业务逻辑要卸载Pay这个类中,通过if,else判断进行业务逻辑的判断。
使用:代码量大量提升,增加了很多个类,但是pay的业务逻辑只会在自己的类中执行,符合单一职责。

从可扩展层面,假如增加云闪付支付途径:
不使用:需要修改Pay类,增加云闪付的逻辑判断,不符合开闭原则。
使用:只需要增加一个云闪付支付途径即可,不需要修改其他业务逻辑,符合开闭原则。

代码耦合层面:
不使用:代码业务逻辑耦合在一起。
使用的:代码耦合性极低。

5、总结

优点:
1)客户端仅仅与高层抽象进行互动,不关系内部对象。
2)符合单一原则。
3)符合开闭原则。

缺点:
在业务对象很多,能抽象很多的业务逻辑而言,会大量的增加类的数量,导致代码的复杂性。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,692评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,482评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,995评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,223评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,245评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,208评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,091评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,929评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,346评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,570评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,739评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,437评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,037评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,677评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,833评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,760评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,647评论 2 354

推荐阅读更多精彩内容