【读书活动感悟分享】—模式冲锋号—《设计模式:可复用面向对象软件的基础》适配器模式与桥接模式在开票服务中的应用_文章

【读书活动感悟分享】—模式冲锋号—《设计模式:可复用面向对象软件的基础》适配器模式与桥接模式在开票服务中的应用

刘海涛
发表于 2025-11-14 23:51:39

适配器模式:让不兼容的接口协同工作

初识适配器模式
刚开始看适配器模式的时候,总觉得这个概念有点抽象。"将一个类的接口转换成客户希望的另一个接口",听起来挺绕的。直到我在代码里看到了InvoiceSGService这个类,才恍然大悟。
// InvoiceSGService 作为适配器
public class InvoiceSGService : IInvoiceSGService
{
    private IInvoiceService InvoiceSrv => HSFService.Proxy();
   
    public InvoiceTaskDataInfo InitInvoiceTaskDataInfo(List invoiceAppID)
    {
        // 身份校验
        SessionServiceUtil.CheckIdentityAuthorization(out SessionContext currentUser);
       
        // 调用HSF服务
        var result = InvoiceSrv.InitInvoiceTaskDataInfo(invoiceAppID);
       
        // 数据脱敏处理
        if (result != null)
        {
            bool nameTuoMin = UserDataPermission.YYTM_RealName(userid, "开票申请");
            // ... 脱敏逻辑
        }
     
        return result;
    }
}

这里InvoiceSGService就是一个典型的适配器。它把HSF服务的接口适配成了SG服务需要的接口,同时在适配过程中还增加了:
身份校验逻辑
数据脱敏处理
权限控制

参数格式转换

适配器模式带来的好处
1.解耦:SG层不需要直接依赖HSF的具体实现,只需要依赖接口
2.扩展性:如果以后HSF服务接口变了,只需要修改适配器,不影响SG层的调用
3.横切关注点:可以在适配器中统一处理日志、监控、权限等横切关注点
踩过的坑
刚开始写适配器的时候,我犯过一个错误:在适配器里做了太多业务逻辑。后来发现这样会导致适配器变得臃肿,而且职责不清。正确的做法应该是:适配器只负责接口转换和横切关注点,业务逻辑应该放在被适配的对象里。


桥接模式:分离抽象与实现
为什么需要桥接模式

桥接模式的核心思想是"将抽象与实现分离,使它们可以独立变化"。这个概念听起来简单,但在实际项目中要识别出什么时候该用桥接模式,还真不容易。

我们项目中的桥接应用
在开票服务中,我们对接了多个第三方开票平台:诺诺、航信、莫奥、蜀道等。每个平台的接口规范、数据格式、调用方式都不一样。如果直接在每个业务方法里写if-else判断,代码会变得非常混乱。
// 抽象接口
public interface IInvoiceInterface
{
    EInvoiceData InitEInvoiceData(EInvoicePushTaskData taskData, InvoiceInterfaceConfig interfaceConfig);
    bool PushEInvoice(EInvoiceTaskParamDetail param, ...);
    void QueryEInvoice(EInvoiceTaskParamDetail param, ...);
}
// 具体实现
public class NuoNuoInvoiceInterface : IInvoiceInterface { ... }
public class HangXinInvoiceInterface : IInvoiceInterface { ... }
public class MoAoInvoiceInterface : IInvoiceInterface { ... }
public class ShuDaoInvoiceInterface : IInvoiceInterface { ... }
// 工厂类创建具体实现
public class InvoiceInterfaceFactory
{
    public static IInvoiceInterface CreateInvoiceInterface(string apiSign)
    {
        switch (apiSign)
        {
            case "NuoNuo":
                return new NuoNuoInvoiceInterface();
            case "HangXin":
                return new HangXinInvoiceInterface();
            // ...
        }
    }
}

这里就体现了桥接模式的思想:
抽象部分:IInvoiceInterface定义了开票接口的抽象
实现部分:各个具体的开票平台实现类
桥接:通过工厂模式在运行时选择具体的实现

桥接模式的优势
1.易于扩展:新增一个开票平台,只需要新增一个实现类,不需要修改现有代码
2.职责清晰:每个实现类只负责一个平台的具体逻辑
3.测试友好:可以针对每个实现类单独编写单元测试
实际开发中的思考
刚开始设计的时候,我考虑过用策略模式。但后来发现,策略模式更侧重于算法的替换,而我们的场景是"同一个抽象接口,不同的实现方式",更适合用桥接模式。
不过说实话,工厂模式+接口的组合,有时候和桥接模式的边界不是那么清晰。我觉得不用太纠结于模式的定义,关键是理解设计思想:把变化的和不变的分离开。
两个模式的对比与选择
适配器 vs 桥接
适配器模式:解决的是"已有接口不兼容"的问题,强调的是"转换"
桥接模式:解决的是"抽象与实现分离"的问题,强调的是"解耦"
在我们项目中:
InvoiceSGService是适配器,因为它把HSF接口适配成了SG接口
IInvoiceInterface及其实现类是桥接,因为它把开票抽象和具体平台实现分离了
什么时候用哪个
我的经验是:
如果两个系统已经存在,接口不兼容,需要让它们协同工作 → 用适配器
如果需要在设计时就考虑多种实现方式,让抽象和实现可以独立变化 → 用桥接
总结
设计模式不是银弹,也不是为了用而用。关键是要理解模式背后的设计思想,然后在合适的场景下应用。适配器和桥接这两个模式,在我们开票服务中都用到了,而且确实让代码结构更清晰、更易维护。
不过说实话,我也纠结过要不要用这些模式,用设计模式,虽然增加了代码的复杂度,但换来了更好的可维护性和扩展性。
最后想说,设计模式的学习不能停留在理论层面,一定要在实际项目中应用和思考。只有在实践中踩过坑、解决过问题,才能真正理解模式的价值。

151 0

评论


意见反馈