本記事では、GoF(Gang of Four)によって提唱されたデザインパターンの一つである「Compositeパターン」について詳しく解説します。
Compositeパターンは、オブジェクトの階層構造を表現するために使用され、個々のオブジェクトとそれらの集まりを同一視することで、一貫した操作が可能となります。
ここでは、その概要や使い方、そしてJava、C++、C#、VB.NETでの実装サンプルを紹介します。
Compositeパターンとは
Compositeパターンは、再帰的に構造を持つオブジェクトを表現するためのデザインパターンです。
このパターンを使用することで、個々の要素と、それらをまとめたコンテナ要素を同一視して操作できるようになります。
Compositeパターンの概要
Compositeパターンは、オブジェクトの階層構造を扱う場合に役立ちます。
単一のオブジェクトと、複数のオブジェクトを同じインターフェースで扱うことで、クライアントコードを簡潔に保つことができます。
例えば、ファイルシステムのディレクトリ構造やUIコンポーネントのツリー構造などでよく利用されます。
Compositeパターンの使い方
Compositeパターンを実装する際は、共通のインターフェースを持つコンポーネントクラスを作成し、それを拡張する「リーフ」と「コンポジット」クラスを定義します。
リーフクラスは具体的な要素を表し、コンポジットクラスは要素の集合を管理します。
これにより、個々のオブジェクトとグループ化されたオブジェクトを同じ方法で操作できるようになります。
Compositeパターンの利点
Compositeパターンの主な利点は、階層構造を持つオブジェクトを一貫して操作できることです。
これにより、複雑なオブジェクト構造を持つシステムであっても、クライアントコードがシンプルで柔軟になります。
Compositeパターン実装サンプル
以下に、Java、C++、C#、VB.NETでのCompositeパターンの実装例を示します。
JavaでのCompositeパターン実装
public interface Component {
void operation();
}
public class Leaf implements Component {
@Override
public void operation() {
System.out.println("Leaf operation");
}
}
public class Composite implements Component {
private List children = new ArrayList<>();
public void add(Component component) {
children.add(component);
}
public void remove(Component component) {
children.remove(component);
}
@Override
public void operation() {
for (Component child : children) {
child.operation();
}
}
}
public class CompositePatternExample {
public static void main(String[] args) {
Composite composite = new Composite();
composite.add(new Leaf());
composite.add(new Leaf());
Composite subComposite = new Composite();
subComposite.add(new Leaf());
composite.add(subComposite);
composite.operation();
}
}
C++でのCompositeパターン実装
#include
#include
class Component {
public:
virtual void operation() = 0;
};
class Leaf : public Component {
public:
void operation() override {
std::cout << "Leaf operation" << std::endl;
}
};
class Composite : public Component {
private:
std::vector children;
public:
void add(Component* component) {
children.push_back(component);
}
void remove(Component* component) {
children.erase(std::remove(children.begin(), children.end(), component), children.end());
}
void operation() override {
for (auto child : children) {
child->operation();
}
}
};
int main() {
Composite composite;
composite.add(new Leaf());
composite.add(new Leaf());
Composite* subComposite = new Composite();
subComposite->add(new Leaf());
composite.add(subComposite);
composite.operation();
return 0;
}
C#でのCompositeパターン実装
using System;
using System.Collections.Generic;
public interface IComponent {
void Operation();
}
public class Leaf : IComponent {
public void Operation() {
Console.WriteLine("Leaf operation");
}
}
public class Composite : IComponent {
private List children = new List();
public void Add(IComponent component) {
children.Add(component);
}
public void Remove(IComponent component) {
children.Remove(component);
}
public void Operation() {
foreach (var child in children) {
child.Operation();
}
}
}
class Program {
static void Main(string[] args) {
Composite composite = new Composite();
composite.Add(new Leaf());
composite.Add(new Leaf());
Composite subComposite = new Composite();
subComposite.Add(new Leaf());
composite.Add(subComposite);
composite.Operation();
}
}
VB.NETでのCompositeパターン実装
Interface IComponent
Sub Operation()
End Interface
Class Leaf
Implements IComponent
Public Sub Operation() Implements IComponent.Operation
Console.WriteLine("Leaf operation")
End Sub
End Class
Class Composite
Implements IComponent
Private children As New List(Of IComponent)()
Public Sub Add(component As IComponent)
children.Add(component)
End Sub
Public Sub Remove(component As IComponent)
children.Remove(component)
End Sub
Public Sub Operation() Implements IComponent.Operation
For Each child In children
child.Operation()
Next
End Sub
End Class
Module Module1
Sub Main()
Dim composite As New Composite()
composite.Add(New Leaf())
composite.Add(New Leaf())
Dim subComposite As New Composite()
subComposite.Add(New Leaf())
composite.Add(subComposite)
composite.Operation()
End Sub
End Module
まとめ
Compositeパターンは、再帰的な階層構造を扱うために非常に有用なデザインパターンです。
このパターンを使用することで、個々のオブジェクトと、それらをまとめた集合を同一のインターフェースで扱えるため、クライアントコードの複雑さを大幅に軽減できます。
Java、C++、C#、VB.NETでの具体的な実装例を参考にして、実際の開発に応用してみてください。
