あるデータと、それを表示する機構があるとします。データは複数種類あるため、描画方法を 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}
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/03/31 12:58