Composite Patternとは
Composite Patternは木構造を伴う再帰的なデータ構造を表すことができます。同じインタフェースを持つ枝と葉が、再帰的な木構造を実現するんですねー。ファイルとディレクトリの関係がまさにComposite Patternです。
Composite パターン Wikipedia
Composite Patternを実装するには
TypescriptでのComposite Patternの実装はinterfaceがあれば実現出来ます。登場人物はComponentとLeafとCompositeです。各要素をクラス図にしてみました。LeafとCompositeはComponentインタフェースを実現しています。CompositeはComponentを集約しています。

Component
LeafとCompositeで共通となるインタフェースです。
木構造を実現する為の機能と、Leaf、Compositeが提供する機能を定義します。
Leaf
木の末端である葉を表すクラスです。
Composite
木の枝を表すクラスです。内部に葉か枝を複数持ちます。Componentの内、主に子要素を操作する機能を実現します。
Composite Patternの実装
何を作るか
ファイルとディレクトリを模した構造を作ってみます。共通のインタフェースであるComponentとファイルを表すItemクラス、ディレクトリを表すDirectoryクラスで構成されています。木構造のrootにDirectoryクラスを配置し、addメソッドでItemかDirectoryを追加して利用します。
Componentが子要素を持つDirectoryクラスか、葉であるItemかを判定する為のisItemメソッドを用意しました。このメソッドによってDirectory,Itemを判定し、再帰処理に利用します。
Componentインタフェースには子要素を操作するメソッドがいくつかあります。Itemクラスではそれらを利用しないので、呼び出した場合は例外を送出する様にしました。例外以外にも無効な値を返却するという方法も考えられます。
実装
//Composite Pattern
//component
interface Component{
add(child:Component):bool;
remove(child:Component):bool;
getChildren():Component[];
getName():string;
isItem():bool;
}
//leaf
class Item implements Component {
constructor(private name: string){
}
add(child:Component):bool{
throw new Error("this object is Item.");
}
remove(child:Component):bool{
throw new Error("this object is Item.");
}
getChildren():Component[]{
throw new Error("this object is Item.");
}
getName():string{
return this.name;
}
isItem():bool{
return true;
}
}
//composite
class Directory implements Component{
items:Component[];
constructor(private name: string){
this.items = new Array();
}
add(child:Component):bool{
this.items.push(child);
return true;
}
remove(child:Component):bool{
for (var i : number = this.items.length - 1; i >= 0; i--) {
if(this.items[i].getName() === child.getName()){
this.items.splice(i, 1);
i++;
}
}
return true;
}
getChildren():Component[]{
return this.items;
}
getName():string{
return this.name;
}
isItem():bool{
return false;
}
}
ソースはこちら
https://github.com/sys1yagi/gof_design_pattern_implemented_in_Typescript/tree/decorator_pattern/src/03.Composite%20Pattern
動作
Composite Patternを用いた木構造でファイルとディレクトリを構成し、再帰的に木を走査して全要素を表示するサンプルです。子要素はpaddingを付けるようにしています。簡単に階層構造を表現出来ます。
Composite Patternの何がおいしいか
Composite PatternはComponentを再帰的に集約する点が拡張性を高めています。今回はConpositeとItemの二つの構成でしたが、ConpositeやItemの種類を増やしたりする事も容易に出来ます。DSLを作る為のInterpreter PatternもComposite Patternの一種です。
終わりに
Webではパンくずメニューや、サイドバーなどのメニューなどで使えると思います。その他にはフォームの入力チェックなんかにも使えるんじゃないかなーと思います。
次回はDecorator Patternを実装してみたいと思います。
