【デザインパターン】【GoF】【Java】Composite パターン

Composite パターン

 * 再帰的な構造の取り扱いを容易
   => つまり、階層構造で表現されるオブジェクトの取扱いを容易にするパターン
   => 例えば、ファイルシステムや
   XMLで表現されるデータ構造(連絡網、部署、プロジェクト(大項目~小項目)など)

デメリット

 * 実装の必要のないメソッドが、インターフェイスに定義される

登場人物

Leaf(葉)

 * 「中身」を表すクラス

Composite (合成物)

 * 「容器」を表すクラス
 * 内容物として、複数の 『Leaf』や 『Composite』の保持が可能
 * 『Component』を実装したオブジェクトに対して再帰処理を行う

Component (部品)

 * 『Leaf』と『Composite』を同一視するためのインタフェース

サンプル

IEntity.java

* Component (部品)
public interface IEntity {
   
   public long getId();
   
   public String getName();

   public void add(IEntity subordinate);
   
   public void printTree();
}

Group.java

* Composite(合成物)
import java.util.ArrayList;
import java.util.List;

public class Group extends Employee {
   private List<IEntity> members;
   
   public Group(long id, String name) {
      super(id, name);
      this.members = new ArrayList<IEntity>();
   }
   
   @Override
   public void add(IEntity member) {
      this.members.add(member);
   }
   
   @Override
   public void printTree() {
      super.printTree();
      for (IEntity member : this.members) {
         member.printTree();
      }
   }
}

Employee.java

* Leaf(葉)
import java.util.ArrayList;
import java.util.List;

public class Employee implements IEntity {
   private long id;
   private String name;
   private List<IEntity> subordinates;
   
   public Employee(long id, String name) {
      this();
      this.id = id;
      this.name = name;
   }
   private Employee() {
      this.subordinates = new ArrayList<IEntity>();
   }
   
   @Override
   public long getId() {
      return this.id;
   }
   
   @Override
   public String getName() {
      return this.name;
   }

   @Override
   public void add(IEntity subordinate) {
      this.subordinates.add(subordinate);
   }
   @Override
   public void printTree() {
      System.out.println(this.id + " : " +this.name);
   }
}

Main.java

* 使用者(クライアント)
public class Main {
   public static void main(String[] args) {
      Group group1 = new Group(10000, "Sales");
      group1.add(new Employee(10001, "Mike"));
      group1.add(new Employee(10002, "Tom"));
      
      Group group2 = new Group(20000, "Developments");
      group2.add(new Employee(20001, "Ted"));
      group2.add(new Employee(20002, "Ken"));
      group2.add(new Employee(20003, "Smith"));
      group2.add(new Employee(20004, "John"));
      
      group1.printTree();
      group2.printTree();
   }
} 

出力結果

10000 : Sales
10001 : Mike
10002 : Tom
20000 : Developments
20001 : Ted
20002 : Ken
20003 : Smith
20004 : John