本文转载自微信公众号「狼王编程」,作者狼王。转载本文请联系狼王编程公众号。
1、概述
桥接模式是一种结构型设计模式, 可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构, 从而能在开发时分别使用。
2、适用场景
1)如果你想要拆分或重组一个具有多重功能的庞杂类 , 可以使用桥接模式。2) 如果你希望在几个独立维度上扩展一个类, 可使用该模式。对象的属性有其他类去实现,不需要自己处理所有工作。3)如果你需要在运行时切换不同实现方法, 可使用桥接模式。桥接模式可替换抽象部分中的实现对象, 具体操作就和给成员变量赋新值一样简单。
3、实例
有以下场景:
- 支付途径:微信,支付宝
- 支付方式:指纹,扫脸
3.1 不使用桥接模式
定义两个枚举
-
- 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;
-
- }
定义支付业务流程:
- 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));
- }
- }
- }
测试类:
- @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("--------------------------------------");
- }
-
- }
结果:
- 当前支付方式是:扫脸
- 当前支付途径是:支付宝
- --------------------------------------
- 当前支付方式是:扫脸
- 当前支付途径是:微信
- --------------------------------------
- 当前支付方式是:指纹
- 当前支付途径是:支付宝
- --------------------------------------
- 当前支付方式是:指纹
- 当前支付途径是:微信
- --------------------------------------
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;
-
- }
定义两个顶层抽象接口:
-
- public interface IPayMethod {
-
- void pay();
- }
-
- public interface IPayWay {
-
- void pay();
- }
定义两种支付方式:
-
- public class FingerPay implements IPayMethod {
-
- @Override
- public void pay() {
- System.out.println("当前支付方式是:" + PayMethodEnum.FINGER.name());
- }
- }
-
- public class FacePay implements IPayMethod {
-
- @Override
- public void pay() {
- System.out.println("当前支付方式是:" + 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("当前支付方式是:" + 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("当前支付方式是:" + PayWaysEnum.ZHIFUBAO.getName());
- payMethod.pay();
- }
- }
测试类:
- @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("--------------------------------------");
- }
-
- }
结果:
- 当前支付方式是:支付宝
- 当前支付方式是:FACE
- --------------------------------------
- 当前支付方式是:微信
- 当前支付方式是:FACE
- --------------------------------------
- 当前支付方式是:支付宝
- 当前支付方式是:FINGER
- --------------------------------------
- 当前支付方式是:微信
- 当前支付方式是:FINGER
- --------------------------------------
4、分析
如上两种方式都实现了四种支付的过程,其中是以支付途径(支付宝、微信)为主,包含两种支付方式(扫脸、指纹)。
从代码量分析:
不使用:代码还是比较少的,但是其实主要业务逻辑要卸载Pay这个类中,通过if,else判断进行业务逻辑的判断。
使用:代码量大量提升,增加了很多个类,但是pay的业务逻辑只会在自己的类中执行,符合单一职责。
从可扩展层面,假如增加云闪付支付途径:
不使用:需要修改Pay类,增加云闪付的逻辑判断,不符合开闭原则。
使用:只需要增加一个云闪付支付途径即可,不需要修改其他业务逻辑,符合开闭原则。
代码耦合层面:
不使用:代码业务逻辑耦合在一起。
使用的:代码耦合性极低。
5、总结
优点:1)客户端仅仅与高层抽象进行互动,不关系内部对象。2)符合单一原则。3)符合开闭原则。
缺点:在业务对象很多,能抽象很多的业务逻辑而言,会大量的增加类的数量,导致代码的复杂性。