孤独プログラマー譚

孤独死が近い。

JavaScript ツリー構造はCompositeパターン

ツリー構造といえばあれだ。

営業部
┗ 1課
 ┗ 山田
 ┗ 鈴木
┗ 2課
 ┗ 佐藤

みたいになってるやつ。

デザインパターンには、このツリー構造をうまく処理できる「Compositeパターン」というものがある。

だが、ツリー構造自体、扱う機会が特に無かったので、Compositeパターンの存在を忘れていた。

「営業部」のようなグループは、中にさらにグループ(1課とか)、あるいは個人(山田とか)を格納できる。
しかし、個人はそれ以上何も格納できない。

以下、グループ・個人共通のインターフェイス

function Component(name) {
  this.children = []
  this.name = name
}
Component.prototype.add = function (child) {
  this.children.push(child)
  return this // メソッドチェーン用
}
Component.prototype.showName = function (indent) {
  var indent = indent || ''

  console.log(indent + this.name)

  indent = indent + '  ' // 子要素の表示はインデントを追加

  for (var i = 0; i < this.children.length; i++) {
    this.children[i].showName(indent)
  }
}

以下、グループを表すクラス。Componentを継承している。

function Composite(name) {
  Component.apply(this, arguments)
}
Composite.prototype = Object.create(Component.prototype)
Composite.prototype.constructor = Composite

以下、個人を表すクラス。同じく、Componentを継承している。
addメソッドは、利用不可になるようオーバーライドしている。

function Leaf() {
  Component.apply(this, arguments)
}
Leaf.prototype = Object.create(Component.prototype)
Leaf.prototype.constructor = Leaf
Leaf.prototype.add = null

ツリー構造を作成して表示。

;(new Component('Sony Music')).add(
  (new Component('乃木坂46')).add(
    new Leaf('白石麻衣')
  ).add(
    new Leaf('西野七瀬')
  )
).add(
  (new Component('欅坂46')).add(
    new Leaf('平手友梨奈')
  ).add(
    new Leaf('長濱ねる')
  )
).showName()

Sony Music
 乃木坂46
  白石麻衣
  西野七瀬
 欅坂46
  平手友梨奈
  長濱ねる

うーん、ツリー構造自体、必要になる機会が無い。出番無いかも…。