Objektově orientované vzory v jazyce JavaScript: Tovární vzor

Organizace kódu nám ušetří spoustu bolesti. Pomocí vlastností objektově orientovaného programování můžeme použít určité návrhové vzory, abychom dosáhli lepší čitelnosti, omezili redundanci a v případě potřeby vytvořili abstrakce. Jedním z takových vzorů je tovární vzor.

Tovární vzor je typ objektově orientovaného vzoru, který se řídí metodikou DRY. Jak název napovídá, instance objektů vytváříme pomocí továrny, která pro nás vyrobí požadovaný objekt.

Podívejme se na velmi jednoduchý příklad použití továrního vzoru pro sestavení objektu alligator. K tomu potřebujeme nejprve vytvořit továrny, které pro nás vytvoří části alligator:

class TailFactory { constructor(props) { this.tailLength = props.tailLength; }};class TorsoFactory { constructor(props) { this.color = props.color; }};class HeadFactory { constructor(props) { this.snoutLenth = props.snoutLenth; }};

Nyní vytvoříme třídu, která funguje jako prostředník mezi skutečnými třídami továren a uživatelem. Nazvěme ji ReptilePartFactory:

class ReptilePartFactory { constructor(type, props) { if(type === "tail") return new TailFactory(props); if(type === "torso") return new TorsoFactory(props); if(type === "head") return new HeadFactory(props); }};

Přejděme nyní k sestavení skutečného aligátora a použijme třídu ReptilePartFactory k získání pro nás požadovaných částí:

let alligator = {};let alligatorProps = { tailLength : 2.5, color: "green", snoutLenth: 1};//gets a tail from the tail factoryalligator.tail = new ReptilePartFactory("tail", alligatorProps); //gets a torso from the torso factoryalligator.torso = new ReptilePartFactory("torso", alligatorProps);//gets a head from the head factoryalligator.head = new ReptilePartFactory("head", alligatorProps);

Podíváme-li se na výše uvedený vzor, zdá se, že bychom mohli použít stejnou třídu ReptilePartFactory k vytvoření částí pro objekty podobné aligátorovi. Továrny na pozadí by se nikdy nemusely dozvědět o povaze výsledného objektu.

Použití továrního vzoru nám tedy přináší určité výhody:

  • Dynamické vytváření objektů:
  • Abstrakce:
  • Je možné jej použít v případech, kdy se o typu objektu rozhoduje za běhu:
  • Opakovaná použitelnost/údržba: Uživatel ve skutečnosti nikdy nemusí přistupovat ke konstruktoru skutečného objektu:

Teď, když už máme určité znalosti o továrním vzoru, prozkoumejme trochu psaní lepšího kódu továrního vzoru.

Výše uvedený příklad používá if-ladder ke zjištění, kterou továrnu zavolat na základě uživatelského vstupu. Jedná se o jednoduchou implementaci, která je intuitivní a není příliš otevřená změnám. Pokud bychom později chtěli přidat nové části, museli bychom ReptilePartFactory narušit. To je porušení zásad SOLID, které říkají: „Softwarové entity (třídy, moduly, funkce atd.) by měly být otevřené pro rozšíření, ale uzavřené pro modifikace.“

Co kdybychom třídy továren uložili do objektu a požadovanou továrnu dílů zavolali pomocí požadovaného dílu jako klíče? Nejprve bychom museli továrny zaregistrovat, bylo by to tak jednoduché jako:

let registeredPartFactories = {};registeredPartFactories = class TailFactory{ ...};registeredPartFactories = class TorsoFactory { ...};registeredPartFactories = class HeadFactory { ...};

A nyní může abstraktní vrstva volat továrny takto:

class ReptilePartFactory { constructor(type, props) { return new registeredPartFactories(props); }};

Tento přístup je mnohem čistší a umožňuje rozšířit naše továrny, aniž by to ovlivnilo kód v ReptilePartFactory.

Na závěr

Existuje několik dalších objektově orientovaných vzorů, které také zvyšují čitelnost a kvalitu. Před použitím vzoru factory si tedy ověřte, zda je na něj skutečný požadavek. Pokud se chystáte opakovaně vytvářet podobné typy objektů a zároveň potřebujete vrstvu pro vytváření nových instancí pomocí těchto objektů a zároveň poskytnout určitou úroveň abstrakce logice vytváření, pak ano – vzor factory je dobrou volbou.

Napsat komentář

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