设计模式-结构型模式_桥接模式(代码片段)

小小工匠 小小工匠     2023-02-01     665

关键词:

文章目录


结构型模式

结构型模式主要是解决如何将对象和类组装成较大的结构, 并同时保持结构的灵活和⾼效。

结构型模式包括:适配器、桥接、组合、装饰器、外观、享元、代理,这7类


概述


桥接模式的主要作⽤就是通过将抽象部分与实现部分分离,把多种可匹配的使⽤进⾏组合。说⽩了核⼼实现也就是在A类中含有B类接⼝,通过构造函数传递B类的实现,这个B类就是设计的 桥

那么这样的桥接模式,在我们平常的开发中有哪些场景呢?

JDBC多种驱动程序的实现、同品牌类型的台式机和笔记本平板、业务实现中的多类接⼝同组过滤服务等。这些场景都⽐较适合使⽤桥接模式进⾏实现,因为在⼀些组合中如果有如果每⼀个类都实现不同的服务可能会出现笛卡尔积,⽽使⽤桥接模式就可以⾮常简单。


Case

模拟⼀个第三⽅平台来承接各个⽀付能⼒,同时使⽤⾃家的⼈脸让⽤户⽀付起来更加容易。那么这⾥就出现了多⽀付与多模式的融合使⽤,如果给每⼀个⽀付都实现⼀次不同的模式,即使是继承类也需要开发好多。

⽽且随着后⾯接⼊了更多的⽀付服务或者⽀付⽅式,就会呈爆炸似的扩展。

这样的场景该如何实现?


Bad Impl

没有⼀个类写不完的需求

public class PayController 

    private Logger logger = LoggerFactory.getLogger(PayController.class);

    public boolean doPay(String uId, String tradeId, BigDecimal amount, int channelType, int modeType) 
        // 微信支付
        if (1 == channelType) 
            logger.info("模拟微信渠道支付划账开始。uId: tradeId: amount:", uId, tradeId, amount);
            if (1 == modeType) 
                logger.info("密码支付,风控校验环境安全");
             else if (2 == modeType) 
                logger.info("人脸支付,风控校验脸部识别");
             else if (3 == modeType) 
                logger.info("指纹支付,风控校验指纹信息");
            
        
        // 支付宝支付
        else if (2 == channelType) 
            logger.info("模拟支付宝渠道支付划账开始。uId: tradeId: amount:", uId, tradeId, amount);
            if (1 == modeType) 
                logger.info("密码支付,风控校验环境安全");
             else if (2 == modeType) 
                logger.info("人脸支付,风控校验脸部识别");
             else if (3 == modeType) 
                logger.info("指纹支付,风控校验指纹信息");
            
        
        return true;
    



  • 提供了⼀个⽀付服务功能,通过提供的必要字段: ⽤户ID 、 交易ID 、 ⾦额 、 渠道 、 模式 ,来控制⽀付⽅式
  • 以上的 ifelse 应该是最差的⼀种写法,即使写 ifelse 也是可以优化的⽅式去写的。

【测试验证】

    @Test
    public void test_pay() 
        PayController pay = new PayController();

        System.out.println("\\r\\n模拟测试场景;微信支付、人脸方式。");
        pay.doPay("weixin_1092033111", "100000109893", new BigDecimal(100), 1, 2);
        
        System.out.println("\\r\\n模拟测试场景;支付宝支付、指纹方式。");
        pay.doPay("jlu19dlxo111","100000109894",new BigDecimal(100), 2, 3);
    

虽然已经满⾜了我们的不同⽀付类型和⽀付模式的组合,但是这样的代码在后⾯的维护以及扩展都会变得⾮常复杂。


Better Impl

接下来使⽤桥接模式来进⾏代码优化,也算是⼀次很⼩的重构。

从上⾯的 ifelse ⽅式实现来看,这是两种不同类型的相互组合。那么就可以把⽀付⽅式和⽀付模式进⾏分离通过抽象类依赖实现类的⽅式进⾏桥接,通过这样的拆分后⽀付与模式其实是可以单独使⽤的,当需要组合时候只需要把模式传递给⽀付即可。

桥接模式的关键是选择的桥接点拆分,是否可以找到这样类似的相互组合,如果没有就不必要⾮得使⽤桥接模式。

【工程结构】


【桥接模式模型结构】

  • 左侧 Pay 是⼀个抽象类,往下是它的两个⽀付类型实现;微信⽀付、⽀付宝⽀付。
  • 右侧 IPayMode 是⼀个接⼝,往下是它的两个⽀付模型;刷脸⽀付、指纹⽀付。
  • 那么, ⽀付类型 × ⽀付模型 = 就可以得到相应的组合。

注意,每种⽀付⽅式的不同,刷脸和指纹校验逻辑也有差异,可以使⽤适配器模式进⾏处理,这⾥不做介绍,可以看适配器模式


【⽀付类型桥接抽象类】

public abstract class Pay 

    protected Logger logger = LoggerFactory.getLogger(Pay.class);

    protected IPayMode payMode;

    public Pay(IPayMode payMode) 
        this.payMode = payMode;
    

    public abstract String transfer(String uId, String tradeId, BigDecimal amount);



  • 在这个类中定义了⽀付⽅式的需要实现的划账接⼝: transfer ,以及桥接接⼝ IPayMode ,并在构造函数中⽤户⽅⾃⾏选择⽀付⽅式。
  • 重点关注 IPayMode payMode ,这部分是桥接的核⼼

【两个⽀付类型的实现】

public class WxPay extends Pay 

    public WxPay(IPayMode payMode) 
        super(payMode);
    

    public String transfer(String uId, String tradeId, BigDecimal amount) 
        logger.info("模拟微信渠道支付划账开始。uId: tradeId: amount:", uId, tradeId, amount);
        boolean security = payMode.security(uId);
        logger.info("模拟微信渠道支付风控校验。uId: tradeId: security:", uId, tradeId, security);
        if (!security) 
            logger.info("模拟微信渠道支付划账拦截。uId: tradeId: amount:", uId, tradeId, amount);
            return "0001";
        
        logger.info("模拟微信渠道支付划账成功。uId: tradeId: amount:", uId, tradeId, amount);
        return "0000";
    



public class ZfbPay extends Pay 

    public ZfbPay(IPayMode payMode) 
        super(payMode);
    

    public String transfer(String uId, String tradeId, BigDecimal amount) 
        logger.info("模拟支付宝渠道支付划账开始。uId: tradeId: amount:", uId, tradeId, amount);
        boolean security = payMode.security(uId);
        logger.info("模拟支付宝渠道支付风控校验。uId: tradeId: security:", uId, tradeId, security);
        if (!security) 
            logger.info("模拟支付宝渠道支付划账拦截。uId: tradeId: amount:", uId, tradeId, amount);
            return "0001";
        
        logger.info("模拟支付宝渠道支付划账成功。uId: tradeId: amount:", uId, tradeId, amount);
        return "0000";
    



  • 分别模拟了调⽤第三⽅的两个⽀付渠道;微信、⽀付宝,当然作为⽀付综合平台可能不只是接了这两个渠道,还会有其很跟多渠道。
  • 可以看到在⽀付的时候分别都调⽤了⻛控的接⼝进⾏验证,也就是不同模式的⽀付( 刷脸 、 指纹 ),都需要过指定的⻛控,才能保证⽀付安全。

【 定义⽀付模式接⼝】

public interface IPayMode 

    boolean security(String uId);



【三种⽀付模式⻛控(刷脸、指纹、密码)】

public class PayCypher implements IPayMode

    protected Logger logger = LoggerFactory.getLogger(PayCypher.class);

    public boolean security(String uId) 
        logger.info("密码支付,风控校验环境安全");
        return true;
    



public class PayFaceMode implements IPayMode

    protected Logger logger = LoggerFactory.getLogger(PayCypher.class);

    public boolean security(String uId) 
        logger.info("人脸支付,风控校验脸部识别");
        return true;
    



public class PayFingerprintMode implements IPayMode

    protected Logger logger = LoggerFactory.getLogger(PayCypher.class);

    public boolean security(String uId) 
        logger.info("指纹支付,风控校验指纹信息");
        return true;
    



实现了三种⽀付模式(刷脸、指纹、密码)的⻛控校验,在⽤户选择不同⽀付类型的时候,则会进⾏相应的⻛控拦截以此保障⽀付安全。


【单元测试】

    @Test
    public void test_pay() 

        System.out.println("\\r\\n模拟测试场景;微信支付、人脸方式。");
        Pay wxPay = new WxPay(new PayFaceMode());
        wxPay.transfer("weixin_1092033111", "100000109893", new BigDecimal(100));

        System.out.println("\\r\\n模拟测试场景;支付宝支付、指纹方式。");
        Pay zfbPay = new ZfbPay(new PayFingerprintMode());
        zfbPay.transfer("jlu19dlxo111","100000109894",new BigDecimal(100));

    

小结

通过模拟微信与⽀付宝两个⽀付渠道在不同的⽀付模式下, 刷脸 、 指纹 、 密码 ,的组合从⽽体现了桥接模式的在这类场景中的合理运⽤。简化了代码的开发,给后续的需求迭代增加了很好的扩展性。

从桥接模式的实现形式来看满⾜了单⼀职责和开闭原则,让每⼀部分内容都很清晰易于维护和拓展,但如果我们是实现的⾼内聚的代码,那么就会很复杂。所以在选择重构代码的时候,需要考虑好整体的设计,否则选不到合理的设计模式,将会让代码变得难以开发。

任何⼀种设计模式的选择和使⽤都应该遵顼符合场景为主,不要刻意使⽤。⽽且统⼀场景因为业务的复杂从⽽可能需要使⽤到多种设计模式的组合,才能将代码设计的更加合理。但这种经验需要从实际的项⽬中学习经验,并提不断的运⽤。

桥接模式(代码片段)

...象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。参照菜鸟教程的桥接模式,具体实现如下图所示#region圆设置类classCircleSetpublic... 查看详情

设计模式(34)-----结构型模式-----桥接设计模式(代码片段)

...象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。... 查看详情

[设计模式c++go]结构型模式:桥接模式(代码片段)

...与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。其定义为:桥梁模式(BridgePattern)也叫做桥接模式,是一个 查看详情

小看--桥接模式(代码片段)

...) 场景提出    桥接模式是属于结构型设计模式;结构型设计模式:关注的是对象和对象之间的关系(继承和组合),结构性设计模式都是在提倡:组合优于继承。    桥接模式    学... 查看详情

结构型模式-桥接模式(代码片段)

桥接模式原文链接:https://www.cnblogs.com/adamjwh/p/9033548.html一、什么是桥接模式? 桥接模式,又叫做桥梁模式,顾名思义,就是有座“桥”,那这座桥是什么呢?就是一条聚合线(下方UML图),比如我们下面会举的例子:手机又手机... 查看详情

设计模式-结构型模式讲解上(适配器桥接组合享元)(代码片段)

一、结构型设计模式上篇,我们呢讲解了创建型设计模式,包括单例、原型、工厂方法,抽象工厂、构建者模式。文章地址:https://blog.csdn.net/qq_43692950/article/details/120165779这篇文章我们来讲解下结构型设计模式ÿ... 查看详情

结构型设计模式之桥接模式(代码片段)

Bridge模式基于类的最小设计原则,通过使用封装、聚合及继承等行为让不同的类承担不同的职责。它的主要特点是把抽象(Abstraction)与行为实现(Implementation)分离开来,从而可以保持各部分的独立性以及应对他们的功能扩展。 ... 查看详情

桥接模式(代码片段)

属于结构型模式,用于抽象与实现解耦。例如:JDBC获取数据库连接,是实现桥接模式的典型。参考:JDBC桥接代码示例publicinterfaceDrawAPIvoiddrawCircle(intradius,intx,inty);publicclassDrawBlueCircleimplementsDrawAPI@OverridepublicvoiddrawCircle(intradius, 查看详情

结构型模式之桥接模式(代码片段)

...实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(HandleandBody)模式或接口(Interface)模式。设想如果要绘制矩形、圆形、椭圆、正方形,我们至少需要4个形状类,但是如果绘制的图形需要具有不同的... 查看详情

设计模式-结构型模式_适配器模式(代码片段)

文章目录结构型模式概述Case场景模拟⼯程BadImplBetterImpl(适配器模式重构代码)MQ消息适配接口适配小结结构型模式结构型模式主要是解决如何将对象和类组装成较大的结构,并同时保持结构的灵活和⾼效。结构型模... 查看详情

设计模式-结构型模式_适配器模式(代码片段)

文章目录结构型模式概述Case场景模拟⼯程BadImplBetterImpl(适配器模式重构代码)结构型模式结构型模式主要是解决如何将对象和类组装成较大的结构,并同时保持结构的灵活和⾼效。结构型模式包括:适配器、桥... 查看详情

设计模式结构型桥接模式(代码片段)

一.概念1.1概念将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和现这两个可变维度的耦合度。1.2结构桥接(Bridge)模式包含以下主要角色:抽象化(Abstract... 查看详情

设计模式结构型模式--桥接模式(代码片段)

1.桥接模式1.1概述现在有一个需求,需要创建不同的图形,并且每个图形都有可能会有不同的颜色。我们可以利用继承的方式来设计类的关系:我们可以发现有很多的类,假如我们再增加一个形状或再增加一种颜... 查看详情

23种设计模式——桥接模式单一职责(代码片段)

文章目录意图什么时候使用桥接真实世界类比桥接模式的实现桥接模式的优缺点亦称:Bridge意图桥接模式是将抽象部分与实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(HandleandBody)模式或接口(In... 查看详情

桥接模式---bridge(代码片段)

桥接模式定义:GOF在《设计模式》中给桥梁模式的定义为:将抽象部分与它的实现部分分离,使它们都可以独立地变化桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式... 查看详情

java设计模式之结构型:桥接模式(代码片段)

一、什么是桥接模式:        桥接,顾名思义,就是用来连接两个部分,使得两个部分可以互相通讯,桥接模式的作用就是为被分离的抽象部分和实现部分搭桥。在现实生活中一个物品在搭配不同的配件... 查看详情

设计模式之桥接模式(代码片段)

本文通过老王和小王买车,引出设计模式中的结构型设计之桥接模式,接着说明设计型模式的概念和代码实现,为了加深理解,会说明适配器设计模式在JDBC中的应用,最后谈谈桥接模式和适配器模式的总结。读者可以拉取完整... 查看详情

设计模式——桥接模式(代码片段)

...同的类层次中,使两个层次可以独立改变。是一种结构型设计模式。Bridge模式基于类的最小设计原则,通过使用封装、聚合及继承等行为让不同的类承担不同的职责。它的主要特点是把抽象(Abstraction)与行为实现(Implementation)分离... 查看详情