2022-12-08
adapter
adapter というのを例で考える。
before
役割は類似するが実装だけでなくインターフェースも異なる 2 つのクラス。
// greeters.ts
export class ShortGreeter {
exec(): void {
console.log('hi');
}
}
export class LongGreeter {
execute(): void {
console.log('hello');
}
}
これらを App から利用する。
// greet-original.ts
import { ShortGreeter, LongGreeter } from './greeters';
class App {
run(): void {
if (Number(process.env['USE_SHORT_GREETER'])) {
const shortGreeter = new ShortGreeter();
shortGreeter.exec();
} else {
const longGreeter = new LongGreeter();
longGreeter.execute();
}
}
}
new App().run();
インターフェースが異なるので、利用する側で分岐する必要が生じている。
% USE_SHORT_GREETER=0 npx ts-node greet-original.ts
hello
% USE_SHORT_GREETER=1 npx ts-node greet-original.ts
hi

after
// greet-adapter.ts
import { ShortGreeter, LongGreeter } from './greeters';
interface Greeter {
do(): void;
}
class ShortGreeterAdapter implements Greeter {
shortGreeter: ShortGreeter;
constructor() {
this.shortGreeter = new ShortGreeter();
}
do() {
this.shortGreeter.exec();
}
}
class LongGreeterAdapter implements Greeter {
longGreeter: LongGreeter;
constructor() {
this.longGreeter = new LongGreeter();
}
do() {
this.longGreeter.execute();
}
}
class App {
run() {
const greeterClass = Number(process.env['USE_SHORT_GREETER'])
? ShortGreeterAdapter
: LongGreeterAdapter;
const greeter = new greeterClass();
greeter.do();
}
}
new App().run();
% USE_SHORT_GREETER=0 npx ts-node greet-adapter.ts
hello
% USE_SHORT_GREETER=1 npx ts-node greet-adapter.ts
hi

メリットは以下か。
- Adapter により各実装の差分が吸収されたので、App からは分岐なくポリモーフィックな呼び出しが可能になった
- たとえば ShortGreeter のインターフェースに変更があった場合、その影響が ShortGreeterAdapter までに留まるようになった