当前位置: 首页 > news >正文

设计模式-结构性模式-桥接模式

1.桥接模式定义

        桥接模式就是将抽象部分与他的实现部分分离,使他们都可以独立的变化;

        桥接模式用一种巧妙地方式处理多层继承存在的问题,用抽象关联来取代传统的多层继承,将类之间的静态继承关系转变为动态的组合关系,使得系统更加灵活,并易于扩展,有效地控制了系统中类的个数;

1.1 桥接模式的优缺点

优点

  • 分离抽象接口及其实现部分,桥接模式使用对象间的关联关系解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的纬度来变化;
  • 在很多情况下,桥接模式可以取代多层继承方案,多层继承方案违背了单一职责原则,复用性差,类的个数多;
  • 桥接模式提高了系统的可扩展性,在不同变化维度中任意扩展一个纬度不需要修改原有系统,符合开闭原则;

缺点

  • 桥接模式的使用会增加系统的理解和设计难度,由于关联关系建立在抽象层,要求开发者一开始就要对抽象层进行设计和编程;
  • 桥接模式要求正确识别出系统中的不同变化的维度,需要一定的经验,因此具有一定的局限性;

1.2 桥接模式使用场景

  •  需要提供平台独立性的应用程序时,如不同数据库的JDBC驱动程序;
  • 需要在某种统一协议下增加更多组件时,如支付场景,行为统一为收款、付款等具体实现为微信、支付宝等;
  • 基于消息驱动的场景,行为统一为发送、接收、处理等,具体的实现为短信、邮箱等;
  • 拆分复杂的类对象,当一个类包含大量对象和方法;
  • 希望从多个独立维度扩展时,如系统功能性和非功能性角度,业务和技术角度;

2.桥接模式的原理

  • 抽象化角色(Abstraction):主要负责定义出该角色的行为,并包含一个对现实化对象的引用;
  • 扩展抽象化角色(RefinedAbstraction):是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法;
  • 实现化角色(Implementor):定义实现化角色的接口,包含角色必须的行为和属性,并供扩展抽象化角色调用;
  • 具体实现化角色(Concrete Implementor):给出实现化角色接口的具体实现;

        桥接模式我理解的就是由一条主线转为树状结构,将类的不同变化维度分离开;

3.桥接模式实现

【实例】

        模拟支付场景,不同的支付工具(支付宝、微信)有着不同的支付方式(密码、指纹)

​​​​​​​

【代码】

        支付模式接口(实现化角色)

public interface IPayMode {//安全校验功能: 对各种支付模式进行风控校验boolean security(String uId);
}

        具体支付模式(具体实现化角色)

//指纹支付及风控校验
public class PayFingerprintMode implements IPayMode {@Overridepublic boolean security(String uId) {System.out.println("指纹支付,风控校验-指纹信息");return true;}
}//密码支付及风控校验
public class PayPasswordMode implements IPayMode {@Overridepublic boolean security(String uId) {System.out.println("密码支付,风控校验-环境安全");return false;}
}

        支付抽象类(抽象化角色)

public abstract class Pay {//桥接对象protected IPayMode payMode;public Pay(IPayMode payMode) {this.payMode = payMode;}//划账功能public abstract String transfer(String uId, String tradeId, BigDecimal amount);}

        支付工具实现(扩展抽象化角色)

public class WxPay extends Pay {public WxPay(IPayMode payMode) {super(payMode);}@Overridepublic String transfer(String uId, String tradeId, BigDecimal amount) {System.out.println("微信渠道支付划账开始......");boolean security = payMode.security(uId);System.out.println("微信渠道支付风险校验: " + uId + " , " + tradeId +" , " + security);if(!security){System.out.println("微信渠道支付划账失败!");return "500";}System.out.println("微信渠道划账成功! 金额: "+ amount);return "200";}
}public class AliPay extends Pay {public AliPay(IPayMode payMode) {super(payMode);}@Overridepublic String transfer(String uId, String tradeId, BigDecimal amount) {System.out.println("支付宝渠道支付划账开始......");boolean security = payMode.security(uId);System.out.println("支付宝渠道支付风险校验: " + uId + " , " + tradeId +" , " + security);if(!security){System.out.println("支付宝渠道支付划账失败!");return "500";}System.out.println("支付宝渠道划账成功! 金额: "+ amount);return "200";}
}

        客户端

Pay wxpay = new WxPay(new PayPasswordMode());
wxpay.transfer("wx_00100100","10001900",new BigDecimal(100));Pay aliPay = new AliPay(new PayFingerprintMode());
aliPay.transfer("jlu1234567","567689999999",new BigDecimal(200));

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 风波中坚守:技术应对突发故障的危与机
  • 我们如何将数据输入到神经网络中?
  • day38.动态规划+MySql数据库复习
  • 视频检索技术为电子商务直播领域带来了前所未有的革新
  • Objective-C中的MVC架构:构建清晰、可维护的iOS应用
  • 【Hot100】LeetCode—101. 对称二叉树
  • web前端之选项卡的实现、动态添加类名、动态移除类名、动态添加样式、激活、间距、节流、tabBar
  • 【精选】基于python的影片数据爬取与数据分析
  • minio使用与注解事务管理
  • 分享一个基于python的抖音短视频流量数据分析与可视化系统Hive大数据源码(源码、调试、LW、开题、PPT)
  • 并查集详解
  • 内网横向移动常用方法
  • 【Docker】Docker学习01 | 什么是docker?
  • sqlserver索引碎片过大如何处理 sqlserver索引碎片查询
  • 淘宝直播弹幕采集
  • es的写入过程
  • iOS小技巧之UIImagePickerController实现头像选择
  • Java IO学习笔记一
  • jquery ajax学习笔记
  • JSONP原理
  • LeetCode18.四数之和 JavaScript
  • Material Design
  • quasar-framework cnodejs社区
  • React Native移动开发实战-3-实现页面间的数据传递
  • React-redux的原理以及使用
  • Spark RDD学习: aggregate函数
  • Unix命令
  • Vue.js源码(2):初探List Rendering
  • vuex 学习笔记 01
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • 仿天猫超市收藏抛物线动画工具库
  • 基于Javascript, Springboot的管理系统报表查询页面代码设计
  • 云大使推广中的常见热门问题
  • 正则与JS中的正则
  • AI又要和人类“对打”,Deepmind宣布《星战Ⅱ》即将开始 ...
  • 国内开源镜像站点
  • ​如何在iOS手机上查看应用日志
  • # Java NIO(一)FileChannel
  • #laravel 通过手动安装依赖PHPExcel#
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • $(selector).each()和$.each()的区别
  • $LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams
  • (17)Hive ——MR任务的map与reduce个数由什么决定?
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (js)循环条件满足时终止循环
  • (webRTC、RecordRTC):navigator.mediaDevices undefined
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (二刷)代码随想录第16天|104.二叉树的最大深度 559.n叉树的最大深度● 111.二叉树的最小深度● 222.完全二叉树的节点个数
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (四)事件系统
  • (四十一)大数据实战——spark的yarn模式生产环境部署
  • (心得)获取一个数二进制序列中所有的偶数位和奇数位, 分别输出二进制序列。
  • .NET 5种线程安全集合
  • .Net Core中Quartz的使用方法
  • .NET DevOps 接入指南 | 1. GitLab 安装