A Composite minta akkor jön jól, ha a problémakör, amit modellezni szeretnénk, egyfajta fa szerkezetként ábrázolható és a fát bejárva kellene műveleteket végeznünk. Ebben az esetben támaszkodhatunk különböző gráf bejáró algoritmusokra a szerkezet bejárásához, de az üzleti logika szempontjából nem biztos, hogy ez a legfontosabb része a problémának, amit meg szeretnénk oldani.
Például a feladatunk az, hogy egy vállalati hierarchiát modellezzünk, amiben lehetnek fejlesztÅ‘k és menedzserek. A konkrét feladat, amit meg szeretnénk oldani az az, hogy egy tetszÅ‘leges munkavállaló esetén az adatait le tudjuk kérdezni. Egy menedzserhez több fejlesztÅ‘ is tartozhat, ezért, ha egy menedzser adait kérdezzük le, akkor a beosztottjait is meg kell jelenÃteni.
Ezt a Composite minta segÃtségével az alábbi módon modellezhetnénk:
internal interface IEmployee
{
string GetDetails();
}
internal class Developer : IEmployee
{
public string Name { get; }
public string Project { get; }
public long Id { get; }
public Developer(long id, string name, string project)
{
Name = name;
Project = project;
Id = id;
}
public string GetDetails()
{
return $"Name: {Name}, Project: {Project}, Id: {Id}";
}
}
internal class Manager : IEmployee
{
public string Name { get; }
public long Id { get; }
public IList<IEmployee> Employees { get;}
public Manager(long id, string name)
{
Name = name;
Id = id;
Employees = new List<IEmployee>();
}
public string GetDetails()
{
StringBuilder sb = new StringBuilder();
sb.AppendLine($"Manager: {Name}, Id: {Id}");
sb.AppendLine("Employees:");
foreach (var employee in Employees)
{
sb.AppendLine(employee.GetDetails());
}
return sb.ToString();
}
}
A kódban az IEmployee interfész egy közös Å‘st definiál, amire függhet a kliens. A felhasználás szempontjából számára teljesen mindegy, hogy egy egyszerű tÃpussal dolgozik, vagy egy olyannal, amely rendelkezik további elemekkel. Ez a metódus a példában a GetDetails() nevet kapta, a jobb nevezéktan miatt. Funkcionalitás szempontjából azonban a ToString() is alkalmazható lett volna a célra.
Az IEmployee két megvalósÃtója a Developer és a Manager osztály, amelyek eltérÅ‘ tulajdonságokkal és eltérÅ‘ GetDetails() implementációval rendelkeznek.
Előnyök
- Lehetővé teszi, hogy könnyebben dolgozzunk fa struktúrákkal, kihasználva a polimorfizmust és a rekurziót
- Open/Closed elvet követi. Újabb elem tÃpusok bevezetése nem töri el a már meglévÅ‘ kódot és nem is kell módosÃtani
Hátrányok
- Nehéz lehet közös interfészt biztosÃtani azoknak az osztályoknak, amelyek funkcionalitása túlságosan eltérÅ‘ Ilyen esetekben túl kell általánosÃtani a közös Å‘s interfészt, ami nehezÃti a kód megértését
- Rekurziót használ az összes előnyével és hátrányával együtt