Intent

  • Skládání objektů do stromových struktur pro reprezentaci celých hierarchií. Kompozitní umožňuje klientům zacházet s jednotlivými objekty akompozicemi objektů jednotně.
  • Rekurzivní kompozice
  • „Adresáře obsahují položky, z nichž každá může být adresářem.“
  • 1-to-many „má a“ až „je a“ hierarchie

Problém

Aplikace potřebuje manipulovat s hierarchickou kolekcí „primitivních „a „kompozitních“ objektů. Zpracování primitivního objektu se provádí jedním způsobem a zpracování složeného objektu se provádí jiným způsobem. nutnost dotazovat se na „typ“ každého objektu před pokusem o jeho zpracování není žádoucí.

Diskuse

Definice abstraktní základní třídy (Component), která určuje chování, které je třeba provádět jednotně pro všechny primitivní a složenéobjekty. Podtřída primitivních a kompozitních objektů je odvozena od třídyComponent. Každý objekt Composite se „spojí“ pouze s abstraktním typem Component, protože spravuje své „děti“.

Tento vzor použijte vždy, když máte „kompozity, které obsahují komponenty,z nichž každá může být kompozitem“.

Metody správy dětí by měly být normálně definovány ve třídě Composite. Bohužel snaha o jednotné zacházení s primitivy a kompozity vyžaduje, aby byly tytometody přesunuty do abstraktní třídy Component. Diskusi o otázkách „bezpečnosti“ versus „průhlednosti“ naleznete v části „Názory“ níže.

Struktura

Kompozity, které obsahují Komponenty, z nichž každá by mohla být Kompozitem.

Menu, která obsahují položky menu, z nichž každá by mohla být menu.

Řádkově-sloupcové správce rozložení GUI, které obsahují widgety, z nichž každá by mohla být řádkově-sloupcovým správcem rozložení GUI.

Adresáře, které obsahují soubory, z nichž každý by mohl být adresářem.

Kontejnery, které obsahují prvky, z nichž každý by mohl být kontejnerem.

Příklad

Kompozice skládá objekty do stromových struktur a umožňuje klientůmjednotlivě zpracovávat jednotlivé objekty a kompozice. Přestože je příklad abstraktní, aritmetické výrazy jsou Kompozity. Aritmetický výraz se skládá z operandu, operátoru (+ – * /) a dalšího operandu. Operandem může být číslo nebo jiný aritmetický výraz. Tedy 2 + 3 a (2 + 3) + (4 * 6) jsou oba platné výrazy.

Kontrolní seznam

  1. Ujistěte se, že váš problém se týká reprezentace hierarchických vztahů „celek-část“.
  2. Zvažte heuristiku: „Kontejnery, které obsahují kontejnery,z nichž každý by mohl být kontejnerem“. Například: „Sestavy, které obsahují komponenty, z nichž každá by mohla být sestavou.“ Rozdělte své doménové koncepty na třídy kontejnerů a třídy kontejnerů.
  3. Vytvořte rozhraní „nejmenšího společného jmenovatele“, které učiní vašekontejnery a kontejnery zaměnitelnými. Mělo by specifikovat chování, které je třeba vykonávat jednotně napříč všemi objekty kontejnerů a kontejnerů.
  4. Všechny třídy kontejnerů a kontejnerů deklarují vztah „is a „k rozhraní.
  5. Všechny třídy kontejnerů deklarují vztah „má a“ od jednoho k mnoha k rozhraní.
  6. Třídy kontejnerů využívají polymorfismus k delegování na své objekty kontejnerů.
  7. Metody správy dětí by měly být normálně definovány ve třídě Composite. Bohužel snaha o jednotné zacházení s objekty Leaf a Composite může vyžadovat, aby byly tyto metody povýšeny na abstraktní třídu Component. Viz Gang ofFour, kde jsou tyto kompromisy mezi „bezpečností“ a „průhledností“ diskutovány.

Pravidla

  • Composite a Decorator mají podobné strukturní diagramy, což odráží skutečnost, že oba spoléhají na rekurzivní kompozici k uspořádání neomezeného počtu objektů.
  • Composite lze procházet pomocí Iteratoru. Visitor může použít operaci nad Composite. Composite může používat Chain ofResponsibility, aby komponenty mohly přistupovat ke globálním vlastnostem prostřednictvím svéhorodiče. Mohl by také použít Decorator k přepsání těchto vlastností na součásti kompozice. Mohl by použít Observer, aby svázal jednu objektovou strukturu s jinou, a State, aby umožnil komponentě měnit své chování při změně jejího stavu.
  • Composite může umožnit složit Mediator z menších částí pomocí rekurzivní kompozice.
  • Decorator je navržen tak, aby umožnil přidávat odpovědnosti k objektůmbez podtřídy. Composite se nezaměřuje na zkrášlování, ale na reprezentaci. Tyto záměry jsou odlišné, ale vzájemně se doplňují. v důsledku toho se Composite a Decorator často používají společně.
  • Kompozita se často kombinují s Composite pro implementaci sdílených listových uzlů.

Opatření

Celý smysl vzoru Composite spočívá v tom, že Composite lze zpracovávat atomicky, stejně jako list. Pokud chcete poskytnout protokolIterátor, fajn, ale myslím, že to je mimo samotný vzor. Jádrem tohoto vzoru je schopnost klienta provádět operace nad objektem, aniž by musel vědět, že uvnitř je mnoho objektů.

Schopnost zacházet s heterogenní kolekcí objektů atomicky(nebo transparentně) vyžaduje, aby rozhraní „správy potomků“ bylo definováno v kořeni hierarchie tříd Composite (abstraktní třídaComponent). Tato volba vás však stojí bezpečnost, protožeklienti se mohou pokoušet dělat nesmyslné věci, jako je přidávání a odebírání objektů z listových objektů. Na druhou stranu, pokud „navrhujete pro bezpečnost“, je rozhraní pro správu dětí deklarováno ve třídě Composite a vy ztrácíte přehlednost, protože listy a Composite mají nyní různá rozhraní.

Implementace vzoru Composite ve Smalltalku obvykle nemají rozhraní pro správu komponent v rozhraní Component,ale v rozhraní Composite. Implementace v jazyce C++ ho obvykle umísťují do rozhraní Component. To je nesmírně zajímavá skutečnost, nad kterou často přemýšlím. Mohu nabídnout teorie, které to vysvětlují, ale nikdo s jistotou neví, proč je to pravda.

Moje třídy Komponent nevědí, že existují Kompozity. Neposkytují žádnou nápovědu pro navigaci po Kompozitech, ani žádnou nápovědu pro změnuobsahu Kompozitu. Je to proto, že bych chtěl, aby základní třída(a všechny její odvozeniny) byly opakovaně použitelné v kontextech, které Kompozity nevyžadují. Když dostanu ukazatel na základní třídu, pokud nutně potřebuji vědět, zda se jedná o Kompozit, použiji dynamic_cast, abych to zjistil. V těch případech, kdy je dynamic_cast příliš nákladné, použiji Visitor.

Běžná stížnost: „Když rozhraní Composite strčím dolů do třídyComposite, jak budu vyčíslovat (tj. procházet) složitou strukturu?“. Moje odpověď zní, že když mám chování, které se vztahuje khierarchiím, jako je ta, která je prezentována ve vzoru Composite, typicky používám Visitor, takže výčet není problém – Visitorks v každém případě přesně ví, s jakým typem objektu má co do činění. Návštěvník nepotřebuje, aby každý objekt poskytoval výčtové rozhraní.

Kompozit vás nenutí zacházet se všemi Komponenty jako s Kompozity. Pouze vám říká, abyste všechny operace, se kterými chcete zacházet „jednotně“, vložili do třídy Component. Pokud s operacemi přidání, odebrání a podobnými operacemi nelze nebo nesmíte zacházet jednotně, pak je nevkládejte do základní třídy Component. Mimochodem, nezapomeňte, že strukturní diagram každého vzoru nedefinuje vzor; pouze znázorňuje to, co je podle našich zkušeností jeho běžnou realizací. Jen proto, že strukturní diagram Composite ukazuje operace správy potomků v bázové třídě Component, neznamená, že všechny implementace vzoru musí dělat totéž.

Podpořte náš web zdarma a vlastněte elektronickou knihu!

  • 22 návrhových vzorů a 8 principů vysvětlených do hloubky
  • 406 přehledných, čtivých stránek bez žargonu
  • 228 přehledných a užitečných ilustrací a diagramů
  • Archiv s příklady kódu ve 4 jazycích
  • Podporována jsou všechna zařízení: Formáty EPUB/MOBI/PDF

Více informací…

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.