読者です 読者をやめる 読者になる 読者になる

osiire’s blog

ふしぎなそふとやさん

GoF in OCaml for Advent Calendar 2012 #2

OCaml Advent Calendar二日目です。
Adapterパターンの次はBridgeパターンですが、これは継承と委譲を組み合わせる話なので前回のAdapterパターンと記述的には同じです。省略。という事で、今回はCompositeパターンをOCamlで記述してみます。

Compositeパターン(wikipedia)

Compositeパターンは木構造を作る時に使えるらしい。共通インターフェイスを定義して枝と葉を抽象的に扱います。

module FileSystem = struct
  (* FileInterfaceに相当する型. Folderが子供としてtのlistを持っている. *)
  type t = File of string| Folder of string * t list

  (* 空白を出力する補助関数 *)
  let printDepthSpace n = for i = 0 to n - 1 do print_string " " done

  (* コンストラクタ *)
  let file name = File name
  let folder name = Folder (name, [])

  (* なんか深さを指定するprinter *)
  let rec defaultMethod depth t =
     printDepthSpace depth;
     match t with
       | File name -> 
          print_string name;
       | Folder (name, children) ->
          print_string name;
          List.iter (defaultMethod (depth + 1)) children

   (* 子供を返す関数. 部分関数なのでoption型を返す *)
   let getChildren = function
      | File _ -> None
      | Folder (_, children) -> Some children

   (* 子供を追加する関数.  *)
   let addComponent child = function
      | File _ -> None
      | Folder (name, children) -> Some (Folder (name, child :: children))

   (* 子供を削除する関数. *)
   let removeComponent child = function
      | File _ -> None
      | Folder (name, children) -> Some (Folder (name, List.filter ((=) child) children))
end

直訳するとこのような感じでしょうか。getChildren, addComponent, removeComponetをFileに適用する事はできないのでNoneが返ります。

次回へ続く! -> http://d.hatena.ne.jp/osiire/20121203