Adapter模式
Adapter(同义词:Wrapper)是最常用的设计模式之一。原因在于, 不兼容接口的适配肯定是软件开发中经常遇到的情况,例如,如果必须集成由另一个团队开发的模块,或者使用第三方库的情况。
Adapter模式的任务说明:
把一个类的接口转换为客户端期望的另一个接口。Adapter可以让因接口不兼容而无法一起工作的类一起工作。
进一步改造关于依赖注入的例子。假设希望使用BoostLog v2(请参阅 http://www.boost.org)进行日志记录,但是我们也希望能够使用其他的日志库替换 BoostLog v2。
解决方案很简单,只需要提供LoggingFacility接口的另一个实现,它将BoostLog 的接口适配到我们使用的接口。
//用BoostTrivialLogAdapter 类实现接口 LoggingFacility
//Boost.Log的Adapter只是LoggingFacility的另一个实现
#include"LoggingFacility.h"
#include<boost/log/trivial.hpp>
class BoostTrivialLogAdapter :public LoggingFacility
{
public:
virtual void writeInfoEntry(std::string entry) override
{
BOOST_LOG_TRIVIAL(info) << entry;
}
virtual void writeWarnEntry(std::string entry) override
{
BOOST_LOG_TRIVIAL(warn) << entry;
}
virtual void writeErrorEntry(std::string entry) override
{
BOOST_LOG_TRIVIAL(error) << entry;
}
};
优点是显而易见的,通过Adapter模式,整个软件系统中只有一个类依赖于第三方日志记录系统。这也意味着,我们的代码不会收到日志所有者特有的语句污染,例如BOOST_LOG_TRIVIAL()。因为Adapter类只是LoggingFacility接口的另一个实现,所以我们也可以使用依赖注入将实例(或者同一个实例)注入想要使用它的所有客户端对象中。
Adapter可以为不兼容的接口提供广泛的适配和转换的可能性。它的适用范围来源于简单的适配,例如操作名称和数据类型的转换,直到支持整个不同的操作集合。在上面的例子中,把对带有一个字符串参数的成员函数的调用,转换成了对stream的插入操作符的调用。
如果要适配的接口很类似,那么接口适配当然很容易。但如果接口之间相差很大,Adapter 的代码实现可能会很复杂。