設(shè)計(jì)模式系列之橋接模式
本文轉(zhuǎn)載自微信公眾號(hào)「狼王編程」,作者狼王。轉(zhuǎn)載本文請(qǐng)聯(lián)系狼王編程公眾號(hào)。
1、概述
橋接模式是一種結(jié)構(gòu)型設(shè)計(jì)模式, 可將一個(gè)大類(lèi)或一系列緊密相關(guān)的類(lèi)拆分為抽象和實(shí)現(xiàn)兩個(gè)獨(dú)立的層次結(jié)構(gòu), 從而能在開(kāi)發(fā)時(shí)分別使用。
2、適用場(chǎng)景
1)如果你想要拆分或重組一個(gè)具有多重功能的龐雜類(lèi) , 可以使用橋接模式。2) 如果你希望在幾個(gè)獨(dú)立維度上擴(kuò)展一個(gè)類(lèi), 可使用該模式。對(duì)象的屬性有其他類(lèi)去實(shí)現(xiàn),不需要自己處理所有工作。3)如果你需要在運(yùn)行時(shí)切換不同實(shí)現(xiàn)方法, 可使用橋接模式。橋接模式可替換抽象部分中的實(shí)現(xiàn)對(duì)象, 具體操作就和給成員變量賦新值一樣簡(jiǎn)單。
3、實(shí)例
有以下場(chǎng)景:
- 支付途徑:微信,支付寶
- 支付方式:指紋,掃臉
3.1 不使用橋接模式
定義兩個(gè)枚舉
- /**
- * 支付方式
- */
- 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;
- }
- /**
- * 支付途徑
- */
- 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;
- }
定義支付業(yè)務(wù)流程:
- public class Pay {
- public void pay(int payMethod, int payWay) {
- if (PayMethodEnum.FACE.getCode() == payMethod) {
- System.out.println("當(dāng)前支付方式是:" + PayMethodEnum.FACE.getName(payMethod));
- } else {
- System.out.println("當(dāng)前支付方式是:" + PayMethodEnum.FINGER.getName(payMethod));
- }
- if (PayWaysEnum.ZHIFUBAO.getCode() == payWay) {
- System.out.println("當(dāng)前支付途徑是:" + PayWaysEnum.ZHIFUBAO.getName(payWay));
- } else {
- System.out.println("當(dāng)前支付途徑是:" + PayWaysEnum.WEIXIN.getName(payWay));
- }
- }
- }
測(cè)試類(lèi):
- @RunWith(SpringRunner.class)
- @SpringBootTest(classes = TestApplication.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("--------------------------------------");
- }
- }
結(jié)果:
- 當(dāng)前支付方式是:掃臉
- 當(dāng)前支付途徑是:支付寶
- --------------------------------------
- 當(dāng)前支付方式是:掃臉
- 當(dāng)前支付途徑是:微信
- --------------------------------------
- 當(dāng)前支付方式是:指紋
- 當(dāng)前支付途徑是:支付寶
- --------------------------------------
- 當(dāng)前支付方式是:指紋
- 當(dāng)前支付途徑是:微信
- --------------------------------------
3.2 使用橋接模式
定義枚舉:
- /**
- * 支付方式
- */
- 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;
- }
- /**
- * 支付途徑
- */
- 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;
- }
定義兩個(gè)頂層抽象接口:
- /**
- * 支付方式接口
- */
- public interface IPayMethod {
- void pay();
- }
- /**
- * 支付途徑接口
- */
- public interface IPayWay {
- void pay();
- }
定義兩種支付方式:
- /**
- * 指紋
- */
- public class FingerPay implements IPayMethod {
- @Override
- public void pay() {
- System.out.println("當(dāng)前支付方式是:" + PayMethodEnum.FINGER.name());
- }
- }
- /**
- * 掃臉
- */
- public class FacePay implements IPayMethod {
- @Override
- public void pay() {
- System.out.println("當(dāng)前支付方式是:" + PayMethodEnum.FACE.name());
- }
- }
定義兩種支付途徑:
- /**
- * 微信
- */
- public class WXPayWay implements IPayWay {
- private IPayMethod payMethod;
- public WXPayWay(IPayMethod payMethod) {
- this.payMethod = payMethod;
- }
- @Override
- public void pay() {
- System.out.println("當(dāng)前支付方式是:" + PayWaysEnum.WEIXIN.getName());
- payMethod.pay();
- }
- }
- /**
- * 支付寶
- */
- public class ZFBPayWay implements IPayWay {
- private IPayMethod payMethod;
- public ZFBPayWay(IPayMethod payMethod) {
- this.payMethod = payMethod;
- }
- @Override
- public void pay() {
- System.out.println("當(dāng)前支付方式是:" + PayWaysEnum.ZHIFUBAO.getName());
- payMethod.pay();
- }
- }
測(cè)試類(lèi):
- @RunWith(SpringRunner.class)
- @SpringBootTest(classes = TestApplication.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("--------------------------------------");
- }
- }
結(jié)果:
- 當(dāng)前支付方式是:支付寶
- 當(dāng)前支付方式是:FACE
- --------------------------------------
- 當(dāng)前支付方式是:微信
- 當(dāng)前支付方式是:FACE
- --------------------------------------
- 當(dāng)前支付方式是:支付寶
- 當(dāng)前支付方式是:FINGER
- --------------------------------------
- 當(dāng)前支付方式是:微信
- 當(dāng)前支付方式是:FINGER
- --------------------------------------
4、分析
如上兩種方式都實(shí)現(xiàn)了四種支付的過(guò)程,其中是以支付途徑(支付寶、微信)為主,包含兩種支付方式(掃臉、指紋)。
從代碼量分析:
不使用:代碼還是比較少的,但是其實(shí)主要業(yè)務(wù)邏輯要卸載Pay這個(gè)類(lèi)中,通過(guò)if,else判斷進(jìn)行業(yè)務(wù)邏輯的判斷。
使用:代碼量大量提升,增加了很多個(gè)類(lèi),但是pay的業(yè)務(wù)邏輯只會(huì)在自己的類(lèi)中執(zhí)行,符合單一職責(zé)。
從可擴(kuò)展層面,假如增加云閃付支付途徑:
不使用:需要修改Pay類(lèi),增加云閃付的邏輯判斷,不符合開(kāi)閉原則。
使用:只需要增加一個(gè)云閃付支付途徑即可,不需要修改其他業(yè)務(wù)邏輯,符合開(kāi)閉原則。
代碼耦合層面:
不使用:代碼業(yè)務(wù)邏輯耦合在一起。
使用的:代碼耦合性極低。
5、總結(jié)
優(yōu)點(diǎn):1)客戶(hù)端僅僅與高層抽象進(jìn)行互動(dòng),不關(guān)系內(nèi)部對(duì)象。2)符合單一原則。3)符合開(kāi)閉原則。
缺點(diǎn):在業(yè)務(wù)對(duì)象很多,能抽象很多的業(yè)務(wù)邏輯而言,會(huì)大量的增加類(lèi)的數(shù)量,導(dǎo)致代碼的復(fù)雜性。


























