前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TypeScript 设计模式之适配器模式

TypeScript 设计模式之适配器模式

作者头像
阿宝哥
发布2020-02-13 17:02:47
6170
发布2020-02-13 17:02:47
举报
文章被收录于专栏:全栈修仙之路全栈修仙之路

一、简介

在实际生活中,也存在适配器的使用场景,比如:港式插头转换器、电源适配器和 USB 转接口。而在软件工程中,适配器模式的作用是解决两个软件实体间的接口不兼容的问题。使用适配器模式之后,原本由于接口不兼容而不能工作的两个软件实体就可以一起工作。

socket-adapter
socket-adapter

(图片来源 - https://meneguite.com/)

二、优缺点

优点
  • 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。
  • 增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。
  • 灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,符合开闭原则。
缺点
  • 过多地使用适配器,会让系统非常零乱,不易整体进行把握。

三、应用场景

  • 系统需要使用现有的类,而这些类的接口不符合系统的需要。
  • 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。

四、模式结构

适配器模式包含以下角色:

  • Target:目标抽象类
  • Adapter:适配器类
  • Adaptee:适配者类
  • Client:客户类

适配器模式有对象适配器和类适配器两种实现,这里我们主要介绍对象适配器。

对象适配器:

adapter-for-object
adapter-for-object

五、实战

具体实现

定义 Target 接口

代码语言:javascript
复制
interface Target {
    request(): void;
}

创建 Adaptee(适配者) 类

代码语言:javascript
复制
class Adaptee {
    public specificRequest(): void {
        console.log("specificRequest of Adaptee is being called");
    }
}

创建 Adapter(适配器)类

代码语言:javascript
复制
class Adapter implements Target {
    public request(): void {
        console.log("Adapter's request method is being called");
        var adaptee: Adaptee = new Adaptee();
        adaptee.specificRequest();
    }
}
使用示例
代码语言:javascript
复制
function show(): void {
    const adapter: Adapter = new Adapter();
    adapter.request();
}

为了更好地理解适配器模式的作用,我们来举一个实际的应用示例。假设你现在拥有一个日志系统,该日志系统会将应用程序生成的所有信息保存到本地文件,具体如下:

代码语言:javascript
复制
interface Logger {
  info(message: string): Promise<void>;
}

class FileLogger implements Logger {
  public async info(message: string): Promise<void> {
    console.info(message);
    console.info('This Message was saved with FileLogger');
  }
}

基于上述的 FileLogger 类,我们就可以在 NotificationService 通知服务中使用它:

代码语言:javascript
复制
class NotificationService {
  protected logger: Logger;
  
  constructor (logger: Logger) {    
    this.logger = logger;
  }

  public async send(message: string): Promise<void> {
    await this.logger.info(`Notification sended: ${message}`);
  }
}

(async () => {
  const fileLogger = new FileLogger();
  const notificationService = new NotificationService(fileLogger);
  await notificationService.send('Hello Semlinker, To File');
})();

以上代码成功运行后会输出以下结果:

代码语言:javascript
复制
Notification sended: Hello Semlinker
This Message was saved with FileLogger

但是现在我们需要使用一种新的方式来保存日志,因为随着应用的增长,我们需要将日志保存到云服务器上,而不再需要保存到磁盘中。因此我们需要使用另一种实现,比如:

代码语言:javascript
复制
interface CloudLogger {
  sendToServer(message: string, type: string): Promise<void>;
}

class AliLogger implements CloudLogger {
  public async sendToServer(message: string, type: string): Promise<void> {
    console.info(message);
    console.info('This Message was saved with AliLogger');
  }
}

但这时对于我们来说,要使用这个新类,我们就可能需要重构旧的代码以使用新的日志存储方式。为了避免重构代码,我们可以考虑使用适配器来解决这个问题。

代码语言:javascript
复制
class CloudLoggerAdapter implements Logger {
  protected cloudLogger: CloudLogger;

  constructor (cloudLogger: CloudLogger) {
    this.cloudLogger = cloudLogger;
  }

  public async info(message: string): Promise<void> {
    await this.cloudLogger.sendToServer(message, 'info');
  }
}

在定义好 CloudLoggerAdapter 适配器之后,我们就可以这样使用:

代码语言:javascript
复制
(async () => {
  const aliLogger = new AliLogger();
  const cloudLoggerAdapter = new CloudLoggerAdapter(aliLogger);
  const notificationService = new NotificationService(cloudLoggerAdapter);
  await notificationService.send('Hello Kakuqo, To Cloud');
})();

以上代码成功运行后会输出以下结果:

代码语言:javascript
复制
Notification sended: Hello Kakuqo, To Cloud
This Message was saved with AliLogger

如你所见,适配器模式是一个非常有用的模式,对于任何开发人员来说,理解这种模式都是至关重要的。

日志系统适配器完整示例

接口定义

代码语言:javascript
复制
interface Logger {
  info(message: string): Promise<void>;
}

interface CloudLogger {
  sendToServer(message: string, type: string): Promise<void>;
}

日志实现类

代码语言:javascript
复制
class AliLogger implements CloudLogger {
  public async sendToServer(message: string, type: string): Promise<void> {
    console.info(message);
    console.info('This Message was saved with AliLogger');
  }
}

适配器

代码语言:javascript
复制
class CloudLoggerAdapter implements Logger {
  protected cloudLogger: CloudLogger;

  constructor (cloudLogger: CloudLogger) {
    this.cloudLogger = cloudLogger;
  }

  public async info(message: string): Promise<void> {
    await this.cloudLogger.sendToServer(message, 'info');
  }
}

通知服务类

代码语言:javascript
复制
class NotificationService {
  protected logger: Logger;
  
  constructor (logger: Logger) {    
    this.logger = logger;
  }

  public async send(message: string): Promise<void> {
    await this.logger.info(`Notification sended: ${message}`);
  }
}

使用示例

代码语言:javascript
复制
(async () => {
  const aliLogger = new AliLogger();
  const cloudLoggerAdapter = new CloudLoggerAdapter(aliLogger);
  const notificationService = new NotificationService(cloudLoggerAdapter);
  await notificationService.send('Hello Kakuqo, To Cloud');
})();

六、参考资源

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020/01/13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、简介
  • 二、优缺点
    • 优点
      • 缺点
      • 三、应用场景
      • 四、模式结构
      • 五、实战
        • 具体实现
          • 使用示例
            • 日志系统适配器完整示例
            • 六、参考资源
            相关产品与服务
            日志服务
            日志服务(Cloud Log Service,CLS)是腾讯云提供的一站式日志服务平台,提供了从日志采集、日志存储到日志检索,图表分析、监控告警、日志投递等多项服务,协助用户通过日志来解决业务运维、服务监控、日志审计等场景问题。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档