質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
デザインパターン

デザインパターンは、ソフトウェアのデザインでよく起きる問題に対して、解決策をノウハウとして蓄積し再利用出来るようにした設計パターンを指します。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Q&A

1回答

1249閲覧

FactoryMethod パターンの正しい使い方が分からない

keymoon

総合スコア5

デザインパターン

デザインパターンは、ソフトウェアのデザインでよく起きる問題に対して、解決策をノウハウとして蓄積し再利用出来るようにした設計パターンを指します。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

0グッド

0クリップ

投稿2021/03/31 12:12

あるデータと、それを表示する機構があるとします。データは複数種類あるため、描画方法を Component インターフェイスとして切り出して、それを個別に描画機構にわたす実装を取っているとします。(HTML を直接吐く等の行儀の悪さには例ということで目を瞑って頂きたいです。)

ts

1interface Component { 2 getHTML(): string; 3} 4 5class SingleComponent implements Component { 6 Content: string; 7 8 constructor(content: string) { 9 this.Content = content; 10 } 11 getHTML() : string { 12 return `<div>${this.Content}</div>`; 13 } 14} 15 16class DoubleComponent implements Component { 17 Content1: string; 18 Content2: string; 19 20 constructor(content1: string, content2: string) { 21 this.Content1 = content1; 22 this.Content2 = content2; 23 } 24 getHTML() : string { 25 return `<div>${this.Content1},${this.Content2}</div>`; 26 } 27} 28 29class ListComponent implements Component { 30 Contents: string[]; 31 32 constructor(content: string[]) { 33 this.Contents = content; 34 } 35 getHTML() : string { 36 return `<table><tbody><tr>${this.Contents.map((x) => `<td>${x}</td>`).join("")}</tr></tbody></table>`; 37 } 38} 39 40interface Renderer { 41 render(component: Component): void; 42}

ここで、配列のデータが単数であれば SingleComponent を、二つであれば DoubleComponent を、それ以上であれば ListComponent を使用するとします。
愚直に実装を行うとするならば以下のようになるはずです。

ts

1let renderer: Renderer; 2function update(): void { 3 const data: string[] = getData(); //データの取得 4 const component = 5 data.Length == 1 ? new SingleComponent(data[0]) : 6 data.Length == 2 ? new DoubleComponent(data[0], data[1]) : 7 new ListComponent(data); 8 renderer.render(component); 9}

ここで、データの生成方法の知識を切り出したいため、各 Component の生成方法をファクトリメソッドにまとめることを考えます。

ts

1interface ComponentFactory { 2 create(data: string[]): Component; 3} 4class SingleComponentFactory implements ComponentFactory { 5 create(data: string[]) : SingleComponent { 6 return new SingleComponent(data[0]); 7 } 8} 9class DoubleComponentFactory implements ComponentFactory { 10 create(data: string[]) : DoubleComponent { 11 return new DoubleComponent(data[0], data[1]); 12 } 13} 14class ListComponentFactory implements ComponentFactory { 15 create(data: string[]) : ListComponent { 16 return new ListComponent(data); 17 } 18}

そうすると生成方法に関する知識を切り出すことはできましたが、以下のようにどのファクトリを選択するかの知識は残ってしまいます。

ts

1let renderer: Renderer; 2function update(): void { 3 const data: string[] = getData(); //データの取得 4 const componentFactory = 5 data.Length == 1 ? new SingleComponentFactory() : 6 data.Length == 2 ? new DoubleComponentFactory() : 7 new ListComponentFactory(); 8 const component = componentFactory.create(data); 9 renderer.render(component); 10}

これも本来ならば切り出したいですが、どのように切り出せば良いのでしょうか?ご教示頂きたいです。また、そもそもこれ以前の切り出しに関する部分にマズそうな箇所があるのであれば、それについても指摘して頂きたいです。

私個人としては以下のようにコンポーネントを直接返すようなメソッドを別途作ってしまうのが良いのかなと現状思っていますが、経験が浅いためにどのようなものがベストプラクティスなのか分からずにいます。

ts

1function CreateComponent(data: string[]): Component { 2 const componentFactory = 3 data.Length == 1 ? new SingleComponentFactory() : 4 data.Length == 2 ? new DoubleComponentFactory() : 5 new ListComponentFactory(); 6 return componentFactory.create(data); 7}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

Productがないから、Factoryパターンで良いと思われますが。。

コンポーネントを直接返すようなメソッドを別途作って

これこそfactoryパターン

こちらが参考になるかも
https://qiita.com/shoheiyokoyama/items/d752834a6a2e208b90ca

投稿2021/03/31 12:49

t_obara

総合スコア5488

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

keymoon

2021/03/31 12:58

回答ありがとうございます。この場合のコンポーネントのようなものを直接返すような関数を作成するパターンを Factory パターンと呼ぶのですね。 > Productがないから、Factoryパターンで良いと思われますが。。 その記事の Factory Method の説明にてあげられている `Product` は `Component` にあたるものだと思っていましたが、少し違うのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問