k-tokitoh

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

メリットは以下か。