项目里没用过设计模式?看看 Nest.js 怎么用的

lxf2023-03-12 17:56:01

设计模式是前人总结的代码架构方式,主要是针对面向对象的代码。

JS 代码在 es6 中加入了 class 的支持,TS 又实现了 interface 和 abstract class 的语法,现在写面向对象的代码容易了很多,所以使用设计模式也就方便了很多。

不知道大家是否在代码里用过设计模式呢?

如果不知道怎么用的话,不妨来看下 Nest.js 是怎么用的吧:

案例 1

Nest.js 除了支持跑一个单独的 http 服务之外,还支持微服务,微服务一般就不是直接处理 http 了,可能是和 Redis 通信、和 Kafaka 等各种中间件通信等等。

各种不同中间件的客户端连接方式不同,而 Nest.js 希望把它们统一管理起来。

怎么统一管理呢?

它定义了这样一个策略接口:

项目里没用过设计模式?看看 Nest.js 怎么用的

有 listen 和 close 两个方法,分别是处理连接建立和断开的。

它内置了 7 个实现类,分别实现了 Grpc、Redis、Kafka、MQTT、Nats、RebbitMQ、TCP 的连接建立和断开的方式:

项目里没用过设计模式?看看 Nest.js 怎么用的

还继承了一个 Server 类,这个类里定义公用的一些属性和方法。

比如 ServerRedis 是这样实现 listen 和 close 的:

项目里没用过设计模式?看看 Nest.js 怎么用的

而 ServerKafka 是这样的:

项目里没用过设计模式?看看 Nest.js 怎么用的

传输方式有多种策略可以选择,通过定义统一的接口来管理它们,这就是策略模式。

然后它又创建了一个工厂类来根据参数创建不同的策略类:

项目里没用过设计模式?看看 Nest.js 怎么用的

这样代码使用的时候是这样的:

项目里没用过设计模式?看看 Nest.js 怎么用的

项目里没用过设计模式?看看 Nest.js 怎么用的

通过 transport 指定不同的传输方式,然后传入 options 即可。

Transport 是一个这样的枚举值:

项目里没用过设计模式?看看 Nest.js 怎么用的

这就是策略模式 + 工厂模式的应用。策略模式定义统一的结构来管理各种策略,工厂模式根据参数创建某个具体的实例

有的同学可能会问了,这样写好处在哪里呢?

好处在于可以灵活的扩展传输策略。

官网有如何创建自定义传输策略的代码,也是继承 Server 实现 CustomTransportStrategy:

项目里没用过设计模式?看看 Nest.js 怎么用的

之后你想使用自己创建的策略类的话就可以这样:

项目里没用过设计模式?看看 Nest.js 怎么用的

源码里做了对自定义 strategy 的处理:

项目里没用过设计模式?看看 Nest.js 怎么用的

如果有自定义 strategy 就用自定义的,否则就用工厂来根据参数创建。

这样就实现了灵活的扩展策略类的需求。

这种灵活性是通过策略模式来实现的,这就是设计模式的好处。

案例 2

Nest.js 其实本身并不处理 http 协议,处理 http 是依赖更底层的 Express 实现的,但是它又不想和 Express 强耦合。

怎么办呢?

于是它定义了个 HttpServer 的接口,里面定义了 http 服务器应该有的所有方法:

项目里没用过设计模式?看看 Nest.js 怎么用的

然后又提供了个抽象类 AbstractHttpAdapter,对 HttpServer 的一些方法做了默认实现。

项目里没用过设计模式?看看 Nest.js 怎么用的

之后 ExpressAdapter 继承了 AbstractHttpAdapter,基于 Express 的 api 提供了这些方法的实现:

项目里没用过设计模式?看看 Nest.js 怎么用的

这样比起直接用 Express 的 api 有什么好处呢?

好处就是可以灵活的切换 http 实现了呀!

比如它还提供了另一个实现,基于 Fastify:

项目里没用过设计模式?看看 Nest.js 怎么用的

这样之后想切换别的 http 的实现就很容易了,并没有和 Express 强耦合。

这又是一个真实的设计模式的应用。

总结

设计模式是针对面向对象的代码的一些代码架构方式,JS 有了 class 的语法,ts 又加入了 interface 和 abstract class,写面向对象的代码容易多了,也就更容易使用设计模式了。

我们看了下 Nest.js 中设计模式的两个案例:

  • 基于策略 + 工厂模式,实现了灵活的扩展传输策略。

  • 基于适配器模式,实现了和 Express 的解耦,可以轻松的切换到另一个 http 处理库。

通过这两个例子可以看出来设计模式是能让代码的可扩展性更强、耦合度更低的。

现在 TS 代码应用设计模式容易了很多,遇到合适场景不妨就尝试用一些设计模式吧,能让你的代码变得更易扩展、更低耦合,写出更优雅的代码。