适配器模式(Adapter Pattern)是一种结构型设计模式,它允许将一个类的接口转换成客户端期望的另一个接口。适配器模式主要用于使原本由于接口不匹配而无法一起工作的两个类能够协同工作。
适配器模式涉及以下几个关键角色:
适配器模式主要有两种形式:类适配器和对象适配器。
在类适配器中,适配器类继承了目标接口,并且同时持有一个被适配者对象。通过继承目标接口,适配器可以将被适配者的方法暴露给客户端。
// 目标接口class Target {request() {}}// 被适配者class Adaptee {specificRequest() {console.log("Adaptee's specific request");}}// 类适配器class Adapter extends Target {constructor(adaptee) {super();this.adaptee = adaptee;}request() {this.adaptee.specificRequest();}}// 客户端const adaptee = new Adaptee();const adapter = new Adapter(adaptee);adapter.request(); // 输出:Adaptee's specific request
在对象适配器中,适配器类持有一个被适配者对象的实例,并实现了目标接口。通过委托,适配器将客户端的请求传递给被适配者。
// 对象适配器class Adapter {constructor(adaptee) {this.adaptee = adaptee;}request() {this.adaptee.specificRequest();}}// 客户端const adaptee = {specificRequest: function() {console.log("Adaptee's specific request");}};const adapter = new Adapter(adaptee);adapter.request(); // 输出:Adaptee's specific request
适配器模式的使用场景包括:
适配器模式使得不同接口的类能够协同工作,使系统更加灵活,同时能够保持类的独立性和可复用性。
假设我们有两个不同的日志库,一个是新日志库 NewLogger,一个是旧日志库 OldLogger,它们的接口不同。我们想要在应用程序中统一使用新日志库,但是现有的代码仍然使用旧日志库。这时候就可以使用适配器模式。
// 新日志库接口class NewLogger {log(message) {console.log(`New Logger: ${message}`);}}// 旧日志库接口class OldLogger {logMessage(msg) {console.log(`Old Logger: ${msg}`);}}// 适配器 - 将旧日志库适配成新日志库接口class OldLoggerAdapter extends NewLogger {constructor(oldLogger) {super();this.oldLogger = oldLogger;}log(message) {// 调用旧日志库的方法this.oldLogger.logMessage(message);}}// 客户端代码,使用新日志库接口const newLogger = new NewLogger();newLogger.log("This is a message from the new logger.");// 适配器让旧日志库适应新日志库接口const oldLogger = new OldLogger();const adaptedLogger = new OldLoggerAdapter(oldLogger);adaptedLogger.log("This is a message from the old logger, adapted to the new logger interface.");
在这个例子中,OldLoggerAdapter
充当适配器的角色,它继承了新日志库的接口,并持有一个旧日志库的实例。在适配器中,它的 log
方法调用了旧日志库的 logMessage
方法,从而实现了旧日志库适配到新日志库的接口。客户端代码使用新日志库接口,而适配器在内部负责将旧日志库的调用适配到新日志库的接口。