作者:京东科技 倪新明
门面模式和适配器模式是代码级的设计模式,而防腐层本质是一种 防御型策略 ,在更高的层级对系统进行解耦
1 关于防腐层
Anti-Corruption Layer(ACL) 如下:
Implement a façade or adapter layer between different subsystems that don't share the same semantics . This layer translates requests that one subsystem makes to the other subsystem. Use this pattern to ensure that an application's design is not limited by dependencies on outside subsystems .
在不共享语义的不同子系统间实现一个门面层或适配层,该层转换一个系统到另一个子系统的请求,使用该模式确保一个应用的设计不被外部系统的依赖所限制。
2 问题背景
一个系统不可能承担所有的职能,大多数情况下都会依赖外部系统的数据或能力。这些外部系统或者遗留系统所关注的领域以及技术选型不尽相同,特别是对于一些老旧的遗留系统往往会面临是技术升级或淘汰的场景。所以,新系统与老系统间的集成往往需要适配他们的协议、数据模型、API或者某些功能特性,但是对于设计人员并不总是希望将这些方面的 “渗入” 到当前系统中。这种情况不仅仅出现在新系统和遗留系统之间,对于系统所依赖的第三方系统也同样适用,因为这些第三方系统可能存在由不同团队开发、技术选型及架构各异、领域模型不一致、可控性差等等诸多不可控因素。
上述场景在实际的业务开发中经常遇到,我们构建的系统并不是孤立的,而是会融入到公司现有的IT系统,甚至会依赖公司外部的三方服务,形式上可能基于HTTP协议的调用,也可能是内部的JSF或OPEN-API调用。这种场景下,外部系统服务提供的模型与内部系统领域上下文下的模型不能确保保持一致。如果在系统设计时不考虑隔离,而是将外部模型直接穿透到内部系统的核心域,则当模型语义产生不一致,或发生变化时,会污染自身领域。
3 解决方案
建立防腐层对不同的子系统进行隔离,该层负责转换两个子系统间的通信。通过引入防腐层,实现不同子系统间的解耦,隔离外部系统的变化对当前系统的影响,避免当前系统的设计由于外部系统的设计和技术实现方式而进行妥协。
防腐层一般会包括模型转换的职能:
• 将当前系统的模型转换成外部系统的模型
• 将外部系统的响应转换成当前系统的模型
除此之外,通过在不同子系统间引入独立的 "层",可以在该层进行例如:
• 外部系统调用进行统一监控
• 对多个子系统的门面封装
• 对模型转换的适配
• 外部调用失败的降级处理
• 统一缓存机制
• .....
防腐层模式适用于:
• 如果老系统迁移至新的系统需要多个迁移阶段,但是依然要维护新系统和老系统间的集成
• 两个或更多子系统间存在不同的语义,但是依然需要相互通信
需要说明的是,如果两个系统间没有特别大的语义差异可能不太适合防腐层模式。也就是说,存在与外部系统交互的场景不一定非要使用防腐层模式,对于模型稳定、语义一致的场景,则没有必要引入额外的一层进行隔离。
4 门面模式与适配器模式
4.1 门面模式
Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use .
门面模式在当前系统和外部系统之间引入了“薄薄的一层”,实现了客户端与外部复杂子系统或组件的解耦,但其并不是降低了系统的复杂性,相应的,它只是对客户端屏蔽了外部系统的复杂性,使得客户端访问子系统更加简单。
• 门面类的职能并不应该对子系统接口的返回数据模型进行封装,其只是负责简化对子系统接口的访问。
• 门面模式并不是对所有的子系统接口都进行覆盖,按需即可
• 门面类不局限于一个,例如,有多个子系统,可以按实际情况建立多个门面类
• 子系统感知不到门面类的存在,而门面类则需要感知各个子系统
• 门面类和子系统耦合,子系统接口的变更会影响到门面类的变更
4.2 适配器模式
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.
通过适配器模式实现两个不兼容接口的无缝集成:
适配器模式本质上适配器模式所承担的职责应该是 "不多不少",只要满足不兼容接口的适配能力即可。
适配器模式目标类和适配者类解耦,易于扩展,符合SOLID的开闭原则,同时,也提高了对已有类的复用性。但,和其他的设计模式一样,适配器模式也会引入额外的类,在一定程度上也会增加系统的复杂性,同样也会增加对代码的认知负载。
5 结语
门面模式和适配器模式是代码级的设计模式,而防腐层本质是一种防御型策略,在更高的层级对系统进行解耦。通常情况下,防腐层包含一系列的门面类和适配器类以及一些转换器类。
• 门面模式对外部系统接口进行简单封装以便更易使用
• 适配器模式负责进行内部系统与外部系统的模型兼容
• 转换器负责对扩系统的模型进行转换