桥接模式

桥接模式

桥接模式实质就是分离抽象和实现,抽象部分有多种,实现部分有多种,耦合在一起很难扩展,将其分离开来就很容易扩展,结构也清晰了

1.桥接模式的本质

桥接模式的本质:分离抽象和实现。

桥接模式最重要的工作就是分离抽象部分和实现部分,这是解决问题的关键。只有把抽象部分和实现部分分离开了,才能够让它们独立地变化;只有抽象部分和实现部分可以独立地变化,系统才会有更好的可扩展性和可维护性。

2.何时选用桥接模式

建议在以下情况中选用桥接模式。

  • 如果你不希望在抽象部分和实现部分采用固定的绑定关系,可以采用桥接模式,来把抽象部分和实现部分分开,然后在程序运行期间来动态地设置抽象部分需要用到的具体的实现,还可以动态地切换具体的实现。

  • 如果出现抽象部分和实现部分都能够扩展的情况,可以采用桥接模式,让抽象部分和实现部分独立地变化,从而灵活地进行单独扩展,而不是搅在一起,扩展一边就会影响到另一边。

  • 如果希望实现部分的修改不会对客户产生影响,可以采用桥接模式。由于客户是面向抽象的接口在运行,实现部分的修改可以独立于抽象部分,并不会对客户产生影响,也可以说对客户是透明的。

  • 如果采用继承的实现方案,会导致产生很多子类,对于这种情况,可以考虑采用桥接模式,分析功能变化的原因,看看是否能分离成不同的纬度,然后通过桥接模式来分离它们,从而减少子类的数目。

3.优缺点

桥接模式的优点

  • 分离抽象和实现部分
    桥接模式分离了抽象部分和实现部分,从而极大地提高了系统的灵活性。让抽象部分和实现部分独立开来,分别定义接口,这有助于对系统进行分层,从而产生更好的结构化的系统。对于系统的高层部分,只需要知道抽象部分和实现部分的接口就可以了。

  • 更好的扩展性
    由于桥接模式把抽象部分和实现部分分离开了,而且分别定义接口,这就使得抽象部分和实现部分可以分别独立地扩展,而不会相互影响,从而大大地提高了系统的可扩展性。

  • 可动态地切换实现
    由于桥接模式把抽象部分和实现部分分离开了,所以在实现桥接的时候,就可以实现动态的选择和使用具体的实现。也就是说一个实现不再是固定的绑定在一个抽象接口上了,可以实现运行期间动态地切换。

  • 可减少子类的个数
    根据前面的讲述,对于有两个变化纬度的情况,如果采用继承的实现方式,大约需要两个纬度上的可变化数量的乘积个子类;而采用桥接模式来实现,大约需要两个纬度上的可变化数量的和个子类。可以明显地减少子类的个数。

4.桥接模式的结构

在这里插入图片描述

  • Abstraction:抽象部分的接口。通常在这个对象中,要维护一个实现部分的对象引用,抽象对象里面的方法,需要调用实现部分的对象来完成。这个对象中的方法,通常都是和具体的业务相关的方法。

  • RefinedAbstraction:扩展抽象部分的接口。通常在这些对象中,定义跟实际业务相关的方法,这些方法的实现通常会使用Abstraction中定义的方法,也可能需要调用实现部分的对象来完成。

  • Implementor:定义实现部分的接口。这个接口不用和 Abstraction中的方法一致,通常是由Implementor 接口提供基本的操作。而Abstraction中定义的是基于这些基本操作的业务方法,也就是说Abstraction定义了基于这些基本操作的较高层次的操作。

  • ConcreteImplementor:真正实现Implementor接口的对象。

5.实现

模拟消息发送

模拟发送消息,发送方式可以是短信发送、邮件发送,消息类型可以是普通消息、加急消息
有以下组合:

  • 短信-普通消息
  • 短信-加急消息
  • 邮件-普通消息
  • 邮件-加急消息

在这里插入图片描述

1.发送消息方式接口及其实现类

/**
 * @description:发送消息方式接口
 */
public interface Message {

    /**
     * 发送消息
     * @param message 消息内容
     * @param toUser 给谁发的消息
     */
    void send(String message,String toUser);
}

/**
 * @description:短信消息
 */
public class SMSMessage implements Message {


    @Override
    public void send(String message, String toUser) {
        System.out.println("发送短信消息,内容:" + message + ",发送给:" + toUser);
    }
}

/**
 * @description:邮件消息
 */
public class EmailMessage implements Message {


    @Override
    public void send(String message, String toUser) {
        System.out.println("发送邮件消息,内容:" + message + ",发送给:" + toUser);
    }
}

2.消息类型抽象类及其实现

/**
 * @description:消息类型
 */
@AllArgsConstructor
public abstract class AbstractMessage {

    protected Message messageImplementor;

    public void sendMessage(String message, String toUser) {
        messageImplementor.send(message,toUser);
    }
}

/**
 * @description:普通消息
 */
public class CommonMessage extends AbstractMessage {

    public CommonMessage(Message messageImplementor) {
        super(messageImplementor);
    }

    @Override
    public void sendMessage(String message, String toUser) {
        super.sendMessage(message, toUser);
    }
}

/**
 * @description:加急消息
 */
public class UrgentMessage extends AbstractMessage {

    public UrgentMessage(Message messageImplementor) {
        super(messageImplementor);
    }

    @Override
    public void sendMessage(String message, String toUser) {
        message = "加急:" + message;
        super.sendMessage(message, toUser);
    }
}

3.测试类

public class Client {

    public static void main(String[] args) {
        //短信消息
        Message sms=new SMSMessage();
        //邮件消息
        Message email=new EmailMessage();

        //短信普通消息
        new CommonMessage(sms).sendMessage("普通消息","张三");
        //邮件普通消息
        new CommonMessage(email).sendMessage("普通消息","张三");
        //短信加急消息
        new UrgentMessage(sms).sendMessage("加急消息","李四");
        //邮件加急消息
        new UrgentMessage(email).sendMessage("加急消息","李四");
    }
}

4.结果
在这里插入图片描述

如果想增加消息发送方式消息类型,只需要增加一个类实现对应接口或抽象类即可。

模拟微信支付支付宝支付

支付类型:微信支付,支付宝支付
支付模式:人脸支付,指纹支付,密码支付
在这里插入图片描述

支付类型代码

/**
 * @description:支付类型抽象类
 */
@AllArgsConstructor
public abstract class Pay {

    //持有支付模式对象
    IPayMode payMode;

    /**
     * 划账
     * @param uid
     * @param tradeId
     * @param amount
     * @return
     */
    public abstract String transfer(String uid, String tradeId, BigDecimal amount);
}

/**
 * @description:微信支付
 */
@Slf4j
public class WxPay extends Pay {

    public WxPay(IPayMode payMode) {
        super(payMode);
    }

    @Override
    public String transfer(String uid, String tradeId, BigDecimal amount) {
        log.info("模拟微信渠道支付划账开始。uId: {} tradeld:{} amount:{}", uid, tradeId, amount);
        log.info("模拟微信渠道支付风控校验。uId: {} tradeld:{} amount:{}", uid, tradeId, amount);
        payMode.security(uid);
        log.info("模拟微信渠道支付划账结束。uId: {} tradeld:{} amount:{}", uid, tradeId, amount);
        return "划账成功";
    }
}

/**
 * @description:支付宝支付
 */
@Slf4j
public class ZfbPay extends Pay {

    public ZfbPay(IPayMode payMode) {
        super(payMode);
    }

    @Override
    public String transfer(String uid, String tradeId, BigDecimal amount) {
        log.info("模拟支付宝渠道支付划账开始。uId: {} tradeld:{} amount:{}", uid, tradeId, amount);
        log.info("模拟支付宝渠道支付风控校验。uId: {} tradeld:{} amount:{}", uid, tradeId, amount);
        boolean security = payMode.security(uid);
        log.info("模拟支付宝渠道支付划账结束。uId: {} tradeld:{} amount:{}", uid, tradeId, amount);
        return "划账成功";
    }
}

支付模式代码

/**
 * @description:支付模式
 */
public interface IPayMode {

    /**
     * 安全校验
     */
    boolean security(String uid);
}

/**
 * @description:人脸识别
 */
@Slf4j
public class FacePayMode implements IPayMode{
    @Override
    public boolean security(String uid) {
        log.info("人脸支付,风险校验脸部信息");
        return true;
    }
}

/**
 * @description:指纹识别
 */
@Slf4j
public class FingerPayMode implements IPayMode{
    @Override
    public boolean security(String uid) {
        log.info("指纹支付,风险校验指纹信息");
        return true;
    }
}

/**
 * @description:密码支付
 */
@Slf4j
public class PwdPayMode implements IPayMode{
    @Override
    public boolean security(String uid) {
        log.info("密码支付,风险校验密码信息");
        return true;
    }
}

测试类

public class BridgeClient {

    public static void main(String[] args) {
        System.out.println("模拟微信支付,人脸支付");
        WxPay wxPay = new WxPay(new FacePayMode());
        wxPay.transfer("100001","1612121561",new BigDecimal(100));

        System.out.println("模拟支付宝支付,指纹支付");
        ZfbPay zfbPay = new ZfbPay(new FacePayMode());
        zfbPay.transfer("100002","151659191",new BigDecimal(200));
    }
}

结果

模拟微信支付,人脸支付
16:57:48.078 [main] INFO com.cong.structuremodel.bridge.real.WxPay - 模拟微信渠道支付划账开始。uId: 100001 tradeld:1612121561 amount:100
16:57:48.084 [main] INFO com.cong.structuremodel.bridge.real.WxPay - 模拟微信渠道支付风控校验。uId: 100001 tradeld:1612121561 amount:100
16:57:48.084 [main] INFO com.cong.structuremodel.bridge.real.FacePayMode - 人脸支付,风险校验脸部信息
16:57:48.084 [main] INFO com.cong.structuremodel.bridge.real.WxPay - 模拟微信渠道支付划账结束。uId: 100001 tradeld:1612121561 amount:100
模拟支付宝支付,指纹支付
16:57:48.085 [main] INFO com.cong.structuremodel.bridge.real.ZfbPay - 模拟支付宝渠道支付划账开始。uId: 100002 tradeld:151659191 amount:200
16:57:48.085 [main] INFO com.cong.structuremodel.bridge.real.ZfbPay - 模拟支付宝渠道支付风控校验。uId: 100002 tradeld:151659191 amount:200
16:57:48.085 [main] INFO com.cong.structuremodel.bridge.real.FingerPayMode - 指纹支付,风险校验指纹信息
16:57:48.085 [main] INFO com.cong.structuremodel.bridge.real.ZfbPay - 模拟支付宝渠道支付划账结束。uId: 100002 tradeld:151659191 amount:200
MVC在桥接模式的体现

其实MVC模式就是一种桥接模式,如下图
在这里插入图片描述

这样看不太明显,如果service有多个实现再看呢,Controller中的两个方法相当于两个实现类,可以调用serviceImpl1也可以调用serviceImpl2
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值