一、桥接模式原理
桥接模式最根本的思想:将抽象部分与实现部分进行分离。两个维度的部分原来是糅杂在一起,现在使用桥接模式将两部分进行分离。
1 举个例子
举个例子:
电商支付方式有以下6种:微信指纹支付、微信人脸支付、微信密码支付;支付宝指纹支付、支付宝人脸支付、支付宝密码支付
如果我们使用传统的方式编写代码:
if(mode=="微信"){
if(method="人脸"){
....
}
if(method="指纹"){
....
}
if(method="密码"){
....
}
}
if(mode=="支付宝"){
if(method="人脸"){
....
}
if(method="指纹"){
....
}
if(method="密码"){
....
}
}
我们很明显能发现问题,如果要再加一种支付类型比如“银行”,那me又会多很多很多ifelse;如果再增加一种支付方式,那么所有支付类型(微信、阿里、银行)都要增加一条ifelse。这样的代码即冗杂又不美观而且违背开闭原则,所以桥接模式登场。
使用桥接模式,就要找到两个维度,上面的例子非常容易找到。第一个维度就是“支付类型”,第二个维度就是“支付方式”。
再找到两个维度后,我们可以进行如下的操作:
- 第一个维度是不是都有“支付”的功能,那么我们将“支付”的功能提取出来放到抽象类Pay里面的transfer方法,其他WeixinPay、ZhiFuBaoPay去继承抽象类Pay并且重写transfer方法。
- 第二个维度都有“支付校验”功能,只是各自实现的方式不太一样,那么我们将“支付校验”的功能提取出来放到接口IPayMode里面,其他FacePayMode、FingerprintMode去实现IPayMode的支付方法security。
- 现在看,我们将两个维度完全分离开来,这两个维度毫不相干。但是我们要将他们组合起来,也就是说我在使用微信支付(维度一)的时候要选择一种校验方式(维度二),所以我们要将第二个维度的对象放在第一个维度中(组合),通过传参的方式选择校验方式。
2 桥接模式引入
那么接下来我们引出桥接模式的四个角色。
Abstraction:抽象化角色 ---- 对应 Pay
RefinedAbstraction:扩展抽象化角色 ---- 对应WeixinPay、ZhiFuBaoPay
Implementor:实现化角色 ---- 对应IPayMode
ConcreteImplementor:具体实现化角色 ---- 对应FacePayMode、FingerprintMode
二、代码
// 抽象化角色
/**
* 支付抽象类
*/
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 WeixinPay extends Pay{
public WeixinPay(IPayMode payMode) {
super(payMode);
}
@Override
public String transfer(String uid, String tradeId, BigDecimal amount) {
System.out.println("微信渠道支付划账开始......");
boolean security = payMode.security(uid);
if(!security){
System.out.println("微信渠道失败");
return "500";
}else{
System.out.println("微信渠道成功");
return "200";
}
}
}
public class ZhiFuBaoPay extends Pay{
public ZhiFuBaoPay(IPayMode payMode) {
super(payMode);
}
@Override
public String transfer(String uid, String tradeId, BigDecimal amount) {
System.out.println("支付宝渠道支付划账开始......");
boolean security = payMode.security(uid);
if(!security){
System.out.println("支付宝渠道失败");
return "500";
}else{
System.out.println("支付宝渠道成功");
return "200";
}
}
}
//实现化角色
public interface IPayMode {
//安全校验功能:对各种支付模式进行风控校验操作
boolean security(String uid);
}
//具体实现化角色
/**
* 指纹支付
*/
public class PayFingerprintMode implements IPayMode {
@Override
public boolean security(String uid) {
System.out.println("指纹支付,风控校验--->指纹信息");
return true;
}
}
/**
* 刷脸支付
*/
public class PayFaceMode implements IPayMode{
@Override
public boolean security(String uid) {
System.out.println("人脸支付,风空校验--->脸部识别");
return true;
}
}
/**
* 密码支付
*/
public class PayCyber implements IPayMode{
@Override
public boolean security(String uid) {
System.out.println("密码支付,风控校验--->环境安全");
return true;
}
}
//test
public class Test {
public static void main(String[] args) {
Pay pay = new WeixinPay(new PayFaceMode());
pay.transfer("1","1",new BigDecimal(100));
}
}
三、优缺点
桥接模式的优点:
- 分离抽象接口及其实现部分.桥接模式使用"对象间的关联关系"解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。
- 在很多情况下,桥接模式可以取代多层继承方案.多层继承方案违背了单一职责原则,复用性差,类的个数多.桥接模式很好的解决了这些问题。
- 桥接模式提高了系统的扩展性,在两个变化维度中任意扩展一个维度都不需要修改原有系统,符合开闭原则。
桥接模式的缺点:
- 桥接模式的使用会增加系统的理解和设计难度,由于关联关系建立在抽象层,要求开发者一开始就要对抽象层进行设计和编程
- 桥接模式要求正确识别出系统中的两个独立变化的维度,因此具有一定的局限性,并且如果正确的进行维度的划分,也需要相当丰富的经验.