middleware パターンを書いてみたかったのでメモ

最近、Node.js デザインパターン (第 2 版) を読んでいるので、載っていたものを自作してみたかったのでメモ。

実装

ミドルウェアの管理クラス

middleware.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
export interface Module {
in?: (n: number) => number | undefined;
out?: (n: number) => number | undefined;
}

export default class Middleware {
private _modules: Function[] = [];

constructor() {}

use(module: Module) {
if (typeof module.in === "function") {
this._modules.unshift(module.in);
}
if (typeof module.out === "function") {
this._modules.push(module.out);
}
}
culc(n: number) {
let tmp = n;
this._modules.forEach((module) => {
tmp = module(tmp);
});

return tmp;
}
flash() {
this._modules = [];
}
viewModules() {
this._modules.forEach((module) => {
console.log(module.toString());
});
}
}

use で、処理を登録。
culc は渡された引数を、useで登録された関数を順に処理して返す。
flash は、登録された関数の削除を実行。
viewModules 登録された関数を先頭から表示。

動作確認

以下のコードで Middleware クラスを検証。

Deno 1.13 環境で、動作確認。

app.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import Middleware, { Module } from "./middleware.ts";

const mid = new Middleware();

mid.use({ in: (n: number) => n + 1 });

console.log(mid.culc(1));
// => 2

mid.flash();

mid.use({ in: (n: number) => n + 2 });
mid.use({ in: (n: number) => n - 1 });
mid.use({ out: (n: number) => n * 2 });

mid.viewModules();
// => (n) => n * 2
// (n) => n - 1
// (n) => n + 2
// in で指定すると、先頭から、
// out で指定すると、後方から追加される。

console.log(mid.culc(1));
// => 4
// 3 つの関数をすべて通過した実行結果が取得された

mid.flash();

const sq = (n: number): number => n * n;

mid.use({ in: (n: number) => n + 2 });
mid.use({ out: sq });
// 関数は外で定義して渡してもいい

console.log(mid.culc(1));
// => 9

mid.flash();

mid.use({ in: ((a = 1) => (n: number) => n + a)() });
// 即時関数の実行結果関数を渡しても用件は満たせる
mid.use({
out: (n: number) => {
return n + 5;
},
});

console.log(mid.culc(1));
// => 7

Express や、Vue で見かける use の意味やっとちゃんと理解した気がします。

ではでは。