Composite - Yapısal Örüntü
Composite örüntüsü parça-bütün ilişkisine sahip ağaç yapılarıdır. Yapıdaki tüm nesnelere aynı işlemi kolayca uygulamayı sağlar.
Composite örüntüsü parça-bütün ilişkisine sahip ağaç yapılarıdır. Yapıdaki tüm nesnelere aynı işlemi kolayca uygulamayı sağlar.
"A composite contains components. Components come in two flavors : composites and leaf elements."
Örüntüdeki Bileşenler
Açıklaması şöyle
Below is the list of classes/objects used in the composite pattern, which has four :Component – Component is the interface (or abstract class) for the composition of the objects and methods for accessing/processing its child or node components. It also implements a default interface to define common functionalities/behaviors for all component classes.Leaf – The leaf class defines a concrete component class, which does not have any further composition. The leaf class implements the component interface. It performs the command/task at its end only.Composite – The composite class defines a concrete component class, which stores its child components. The composite class implements the component interface. It forwards the command/task to the composite objects it contains. It may also perform additional operations before and after forwarding the command/task.Client – The client class uses the component interface to interact/manipulate the objects in the composition (Leaf and Composite).
Hiyerarşi
Yapısal olarak şöyledir. Composite Base nesnenin listesini içerir.Base
^
|
Composite --(has) List of Base
Klasik Örnek
GUI'de en üstte bulunan Frame/Panel gibi bir nesne diğer nesneleri içerir. Ana bileşene show() komutu gönderilince içerdiği diğer tüm bileşenlere de aynı komutu gönderir.İş Yükü Dağıtımı - Work Load Distribution
Elimizde şöyle bir arayüz olsun
public interface Worker { void assignWork(Employee manager, Work work); void performWork();}
Bu arayüzü gerçekleştiren şöyle sınıflar olsun
public abstract class Employee implements Worker { ... }public class Engineer extends Employee { private List<Work> works = new ArrayList<>(); ... @Override public void assignWork(Work work) { this.works.add(work); } @Override public void performWork() { works.stream().forEach(work -> {...}); works.clear(); }}
public class Manager extends Employee { List<Employee> managingEmployees = new ArrayList<>();
public boolean manages(Employee employee) { return managingEmployees.add(employee); } @Override public void assignWork(Work work) { //Tüm işleri astlara eşit böl ve ata } @Override public void performWork() { managingEmployees.stream().forEach(employee -> employee.performWork()); }}
En üst yöneticiye işleri atadıktan sonra tüm astlara işlerin dağıtan kod şöyledir.
public static void main(String[] args) { Engineer ajay =...; Engineer vijay =...; Engineer jay =...; Engineer martin =...; Manager kim =...; Engineer anders = ...; Manager niels = ...; Engineer robert = ...; Manager rachelle = ...; Engineer shailesh = ...; kim.manages(ajay); kim.manages(martin); kim.manages(vijay); niels.manages(jay); niels.manages(anders); niels.manages(shailesh); rachelle.manages(kim); rachelle.manages(robert); rachelle.manages(niels); rachelle.assignWork(...); rachelle.performWork();}
Mesaj Örneği
XML yapısını Composite olarak okuyan bir yapı olsun. Her nesne FieldDefinition arayüzünden kalıtır.RecordDefiniton has --> AlternativeFieldDefinitionDaha sonra bu definition'ları bir composite mesaj haline getirelim.Her bir field kendi içinde FieldDefinition yapısını içerir Her nesne CompositeData ata sınıfından kalıtır.
--> NormalFieldDefinition
--> SpareFieldDefinition
GenericRecord has --> AlternativeFieldBöylece stream'e okuma yazma yapabilen generic bir composite elde ederiz.
--> NormalField
--> AdaptorField
Bir başka örnek
Önce bir ata sınıf veya arayüz yaratılır. Vehicle isimli bir sınıfımız olsun
public abstract class Vehicle
{
public void drive(int distance) {
System.out.println("Drove " + distance + ". Vroom vroom!");
}
public abstract int getWeight();
// etc.
}
Daha sonra ata sınıfı gerçekleştiren başka sınılar yazılır.public class Car extends Vehicle
{
protected int weight;
// ...
@Override
public int getWeight() {
return this.weight;
}
}
Son olarak bu sınıflar bünyesinde barındıran bir composite yaratılır.public class CarCarrier extends Vehicle
{
protected int weight;
protected Vehicle[] cars;
// ...
@Override
public int getWeight() {
int weight = this.weight;
for(Vehicle car : cars) {
weight += car.getWeight();
}
return weight;
}
}
Örnek
Elimizde şöyle bir arayüz olsun. Burada bir composite içinde olabilecek root, leaf ve ara düğümler gösteriliyor.
interface Human {void addChild(Human child);void addParent(Human parent);}
Elimizde şöyle sınıflar olsun
public class GrandParent implements Human {private List<Human> children = new ArrayList<>();@Overridepublic void addChild(Human child) {childs.add(child);}@Overridepublic void addParent(Human parent) {}}public class Parent implements Human {private List<Human> children = new ArrayList<>();private List<Human> parents = new ArrayList<>();@Overridepublic void addChild(Human child) {children.add(child);}@Overridepublic void addParent(Human parent) {parents.add(parent);}}public class Child implements Human {private List<Human> parents = new ArrayList<>();@Overridepublic void addChild(Human child) {}@Overridepublic void addParent(Human parent) {parents.add(parent);}}
Şöyle yaparız
Child child = ...Parent father = ...Parent mother = ...child.addParent(father);child.addParent(mother);father.addChild(child);mother.addChild(child);GrandParent granpa = ...;granpa.addChild(father);father.addParent(granpa);
Composite veri yapısını dolaşması (traverse) işlemi zor olabiliyor.
Hiç yorum yok:
Yorum Gönder