Kendi içlerinde birbirlerinden farklı olan bir grup nesnenin sanki tek bir bütün nesneymiş gibi kullanılmasını bileşik kalıp sağlar. Bileşik kalıpların görevi, nesneleri bir ağaç yapısında birleştirip uygulamanın genelindeki parça bütün ilişkisini yeniden düzenleyip şekillendirmektir.
Kullanıldığı durumlar;
Yazılımcı, kullanıcının isteği doğrultusunda aynı türden veya farklı türlerden bir nesne topluluğu kullanmak zorunda ise, karmaşadan ve karışıklıktan kurtulmak için bileşik kalıp kullanabilir.
Bileşik Tasarım Kalıbının Yapısı
Bileşik kalıbın içinde yer alan yapılar aşağıda sıralanmıştır.
- Bileşen(Component)
- Bileşikler için temel soyut tanımlamalardır.
- Bileşik işlemi için nesnelerin arayüzünü oluşturur.
- Tüm sınıfların arayüzündeki varsayılan davranışı gerçekleştirir.
- Yavru bileşenlere ulaşmamızı ve onları kontrol etmemizi sağlamak için bir arayüz tanımlar.
- Yaprak (Leaf)
- Bileşik işleminde yavru nesneleri temsil eder.
- Tüm bileşen metodları yapraklar tarafından tamamlanır.
- Bileşik (Composite)
- Yaprakları olan bileşenleri temsil eder.
- Çocuklarını yönlendiren metodları gerçekler.
- Genelde çocuklarını görevlendirerek bileşik metodlarını gerçekler.
Bileşik tasarım kalıbının UML diyagramı aşağıdaki şekildedir.
Bu uygulamada öncelikle Component adındaki bileşenin içeriği tanımlanır. Bu bileşenden kalıtımsal olarak türeyen Composite adında bileşik sınıfını ve Leaf adında yaprak sınıflarını yaratıp, bu sınıflar altında kullanılacak olan metodlar tanımlanır. Tasarım kalıbı tanımlandıktan sonra, yazılan kalıbın nasıl kullanıldığını görmek için küçük bir program parçası aşağıda yazılmıştır. Bu örnek program parçasında bileşen, bileşik ve yaprakların aralarında nasıl ilişkiye sahip oldukları görülmektedir.
Bu yapıların anlaşılması için gerçekleştirilen C# uygulaması aşağıda görülmektedir.
using System;
using System.Collections.Generic;
namespace Composite
{
abstract class Component
{
protected string name;
public Component(string name)
{
this.name = name;
}
public abstract void Add(Component c);
public abstract void Remove(Component c);
public abstract void Display(int depth);
}
class Composite : Component
{
private List<Component> _children = new List<Component>();
public Composite(string name) : base(name)
{ }
public override void Add(Component component)
{
_children.Add(component);
}
public override void Remove(Component component)
{
_children.Remove(component);
}
public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + name);
foreach (Component component in _children)
{
component.Display(depth + 2);
}
}
}
class Leaf : Component
{
public Leaf(string name) : base(name)
{ }
public override void Add(Component c)
{
Console.WriteLine("Cannot add to a leaf");
}
public override void Remove(Component c)
{
Console.WriteLine("Cannot remove from a leaf");
}
public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + name);
}
}
class MainApp
{
static void Main()
{
Composite root = new Composite("root");
root.Add(new Leaf("Leaf A"));
root.Add(new Leaf("Leaf B"));
Composite comp = new Composite("Composite X");
comp.Add(new Leaf("Leaf XA"));
comp.Add(new Leaf("Leaf XB"));
root.Add(comp);
root.Add(new Leaf("Leaf C"));
Leaf leaf = new Leaf("Leaf D");
root.Add(leaf);
root.Remove(leaf);
root.Display(1);
Console.ReadKey();
}
}
}