Adapterパターン
概要
インターフェースの違うオブジェクトを繋ぎ合わせるパターン
例
VanillaShake
interface VanillaShake {
eat(): void;
}
Drink
interface Drink {
drink(): void;
}
haveMeals
const haveMeals = (food: Food, drink: Drink) => {
food.eat()
drink.drink()
}
この引数に直接VanillaShakeを渡すことはできない
vanillaShakeAdapter
const vanillaShakeAdapter = (vanillaShake: VanillaShake) => ({
drink: () => vanillaShake.eat()
})
このメソッドにより、インターフェースの違うVanillaShakeをDrinkとして扱えるようになる
haveMeals(food, vanillaShakeAdapter(vanillaShake))
使い所
- すでに出来上がっていて変更コストが高いメソッドやクラスを別のインターフェースに当て嵌めたい時
- 外部ライブラリなどで本体のコードを触りづらい時
Bridgeパターン
Adapterは2つの異なるinterfaceを繋げるパターン。
しかし、Bridgeパターンは処理の中身を外から注入するパターン
Bridgeを使わないと以下のようになってしまう
// リモコン
const tvController = {
sendIr: () => {
console.log("IR signal sent") // 赤外線を送る処理
},
turnOn: () => {
sendIr()
console.log("turn on tv")
}
}
// 物理スイッチ
const tvSwitch = {
turnOn: () => {
console.log("turn on tv")
}
}
const radioController = {
sendIr: () => {
console.log("IR signal sent") // 赤外線を送る処理
},
turnOn: () => {
sendIr()
console.log("turn on radio")
}
}
const radioSwitch = {
turnOn: () => {
console.log("turn on radio")
}
}
実行命令を送る方法(リモコンや物理スイッチ)が増えるとデバイス分の命令方法の定義が必要になる デバイスが増えると、同じような命令方法でも再度定義が必要になる
デバイスの動作(機能)と命令方法(実装)を分離して、命令にを外から注入するようにすれば、デバイス x 命令の定義が必要なくなる
interface Device = {
turnOn: () => void;
}
const tv: Device = {
turnOn: () => {
console.log("turn on tv")
}
}
const radio: Device = {
turnOn: () => {
console.log("turn on radio")
}
}
const createController = (device: Device) => ({
turnOn: () => {
console.log("IR signal sent") // 赤外線を送る処理
device.turnOn()
}
})
const createSwitch = (device: Device) => ({
turnOn: () => {
device.turnOn()
}
})
const tvController = createController(tv)
const tvSwitch = createSwitch(tv)
const radioController = createController(radio)
const radioSwitch = createSwitch(radio)