Analogia z życia:
Oddając samochód do mechanika powierzamy mu kluczyki i oczekujemy naprawy zepsutych części. Mechanik po odebraniu kluczyków wjeżdża samochodem na warsztat i zleca swoim pracownikom konkretne zadania: wymianę zderzaka, prostowanie blachy, lakierowanie. Z naszego punktu widzenia załatwiamy wszystkie te sprawy z jedną osobą (kierownikiem warsztatu), nie musimy martwić się o to, kto będzie wykonywał poszczególne zadania.
Zastosowanie:
Wszędzie tam, gdzie chcemy, aby kod klienta wiedział jak najmniej o procesie, który woła. Klient powinien być niezależny od tego procesu i przechowywać jedynie referencję do obiektu kompozytu, który dba o to, by wywołać odpowiednie konkretne składowe procesu.
Zasada działania:
Klient zawiera referencję na pewien interfejs. Interfejs ten jest implementowany przez konkretne typy, jak również przez specjalny typ - kompozyt, który zawiera także kolekcję elementów implementujących interfejs.
public interface ICarMechanic { void Repair(Car instance); } public class Tinsmith : ICarMechanic { public void Repair(Car instance) { instance.CrackedBody = false; } } public class WheelChanger : ICarMechanic { public void Repair(Car instance) { instance.WorkingWheels = 4; } } public class BumperChanger : ICarMechanic { public void Repair(Car instance) { instance.HasNewBumper = true; } } //composite public class CarService : ICarMechanic { private List<ICarMechanic> _mechanics; public CarService(IEnumerable<ICarMechanic> mechanics) { _mechanics = new List<ICarMechanic>(mechanics); } public void Repair(Car instance) { if (instance.BrokenWheel) { RepairIfAny<WheelChanger>(instance); } if (instance.BrokenBody) { RepairIfAny<WheelChanger>(instance); } if (instance.BrokenWheel) { RepairIfAny<BumperChanger>(instance); } } private void RepairIfAny<T>(Car instance) where T : ICarMechanic { var mechanic = _mechanics.OfType<T>().FirstOrDefault(); if (mechanic != null) mechanic.Repair(instance); } }
Wyekstraktowanie logiki napraw do klasy - kompozytu znacznie ułatwia kod po stronie klienta wołającego usługę naprawy.
public class CarOwner { private Car _car; private ICarMechanic _mechanicContact; public CarOwner(Car car, ICarMechanic contact) { _car = car; _mechanicContact = contact; } public void RenewCar() { _mechanicContact.Repair(_car); Console.WriteLine("Car has been repaired"); } }
Cały proces startuje przez stworzenie odpowiednich zależności dla kompozytu:
static void Main(string[] args) { var mechanicsSvc = new CarService( new ICarMechanic[] { new BumperChanger(), new WheelChanger(), new Tinsmith() }); var car = new Car() { BrokenBody = true, BrokenWheel = true, HasNewBumper = false }; var owner = new CarOwner(car, mechanicsSvc); owner.RenewCar(); Console.ReadKey(); }
Brak komentarzy:
Prześlij komentarz