
シングルトンが理解できたら、次にファクトリメソッドを理解すると、設計力がアップします。
ファクトリメソッドは、オブジェクトの
生成処理をサブクラス(または関数)に任せるデザインパターンです。
「どのクラス(型)のインスタンスを作るか」を
呼び出し元が意識しないようにするということですが、この説明だと意味わかりませんよね。
わかりやすく言うと、「ハンバーガーを注文したら、どの店でも“注文口”は同じだけど、実際に作るのは“各店舗の厨房”が違う」と言うような感じなのだそうです。
とりあえず、ソースコードを使って、理解しましょう。
サンプルプログラム(クラス型)
それでは、実際に今回もJavascript(ES)のコードを使って、サンプルを見てみましょう。
プロダクト(作られる側)
class Dog {
speak() {
return "わん!";
}
}
class Cat {
speak() {
return "にゃー!";
}
}
ファクトリ(作る仕組みをもつ側)
class AnimalFactory {
createAnimal(type) {
switch (type) {
case "dog":
return new Dog();
case "cat":
return new Cat();
default:
throw new Error("Unknown animal type");
}
}
}
利用側(作る方法を知らなくてもOK)
const factory = new AnimalFactory();
const dog = factory.createAnimal("dog");
const cat = factory.createAnimal("cat");
console.log(dog.speak()); // → "わん!"
console.log(cat.speak()); // → "にゃー!"
ポイント解説
new Dog() や new Cat() を直接呼ばず、Factoryに任せるのが、ファクトリメソッドです。
新しい種類(例:Bird)を追加しても、呼び出し側のコードを変更せずに拡張できるのが特徴です。
拡張性の想定されるシステムでは、この方式で設計しておくと、その後の開発が楽になるのがよくわかりますね。
デメリット
サンプルコードをわかる通り、クラスが増えるので、命名ルールなどに気を使う必要があります。
単純な処理では逆にコードが複雑に見えるので、何でもかんでもファクトリ化すると言うのも良くないかもです。(設計思想によります)
関数方サンプル
unction createAnimal(type) {
const animals = {
dog: () => ({ speak: () => "わん!" }),
cat: () => ({ speak: () => "にゃー!" }),
};
if (!animals[type]) throw new Error("Unknown animal type");
return animals[type]();
}
const a1 = createAnimal("dog");
const a2 = createAnimal("cat");
console.log(a1.speak()); // → "わん!"
console.log(a2.speak()); // → "にゃー!"
小規模スクリプトなら、こうした関数ファクトリの形が便利です。
あとがき
個人的に、switch文使って、分岐を作るやり方もよく使います。
ファクトリに送られてきた、key値(サンプルのdogやcat)を判別して、任意のclassや関数を実行する手法ですね。
プロダクトをシングルトンにして、それをwrapするように、ファクトリの構造にすると、その後の機能追加など便利にできそうです。
まあ、デザインパターンを知らない人でも、独自にこうした処理を作っている場合も多いと思いますが、
ちゃんと構造体として理解しておくことで、いざ自分がシステム設計をする際に、迷わずに構築できるというメリットが大きいですね。
0 件のコメント:
コメントを投稿