Organisering av kod kommer att rädda oss från mycket smärta. Med hjälp av funktionerna i objektorienterad programmering kan vi använda vissa designmönster för att uppnå bättre läsbarhet, minska redundans och vid behov skapa abstraktioner. Ett sådant mönster är fabriksmönstret.
Fabriksmönstret är en typ av objektorienterat mönster som följer DRY-metodiken. Som namnet antyder skapas objektinstanser genom att använda en fabrik som tillverkar det önskade objektet åt oss.
Låt oss ta en titt på ett mycket enkelt exempel på hur fabriksmönstret används för att sätta ihop ett alligator
objekt. För att göra det måste vi först skapa fabriker som skapar alligator
-delarna åt oss:
class TailFactory { constructor(props) { this.tailLength = props.tailLength; }};class TorsoFactory { constructor(props) { this.color = props.color; }};class HeadFactory { constructor(props) { this.snoutLenth = props.snoutLenth; }};
Nu skapar vi en klass som fungerar som en mellanhand mellan de faktiska fabriksklasserna och användaren. Låt oss kalla detta för 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); }};
Låt oss gå vidare och sätta ihop den faktiska alligatorn nu och använda ReptilePartFactory
för att få de nödvändiga delarna åt oss:
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);
Om vi tittar på mönstret ovan, verkar det som om vi skulle kunna använda samma ReptilePartFactory
för att skapa delar för alligatorliknande objekt. Fabrikerna i bakgrunden skulle aldrig behöva känna till det slutliga objektets natur.
Därmed ger användningen av fabriksmönstret oss vissa fördelar:
- Dynamiskt skapande av objekt: Det kan användas i fall där objektets typ bestäms vid körning.
- Abstraktion:
- Återanvändbarhet/underhåll: Användaren behöver egentligen aldrig få tillgång till det faktiska objektets konstruktör: Samma fabriker kan användas för liknande objekt och det gör att vi enkelt kan lägga till/ta bort nya objektklasser utan att ändra en massa kod.
Nu när vi har en viss förståelse för fabriksmönstret ska vi utforska lite hur man skriver bättre kod för fabriksmönstret.
Exemplet ovan använder en if-ladder för att ta reda på vilken fabrik som ska anropas baserat på användarens inmatning. Detta är en enkel implementering, intuitiv och inte särskilt öppen för ändringar. Om vi har nya delar att lägga till senare måste vi störa ReptilePartFactory
. Detta är ett brott mot SOLID-principerna, där det står ”Programvaruenheter (klasser, moduler, funktioner etc.) bör vara öppna för utvidgning, men stängda för ändring”.
Hur vore det om vi lagrar fabriksklasserna i ett objekt och anropar den önskade delfabriken genom att använda den del vi vill ha som nyckel? Först måste vi registrera fabrikerna, det skulle vara så enkelt som:
let registeredPartFactories = {};registeredPartFactories = class TailFactory{ ...};registeredPartFactories = class TorsoFactory { ...};registeredPartFactories = class HeadFactory { ...};
Och nu kan det abstrakta lagret anropa fabrikerna så här:
class ReptilePartFactory { constructor(type, props) { return new registeredPartFactories(props); }};
Detta tillvägagångssätt är mycket renare och gör det möjligt att utöka våra fabriker utan att påverka koden i ReptilePartFactory
.
Slutsatsen
Det finns flera andra objektorienterade mönster som också ökar läsbarheten och kvaliteten. Så innan du använder fabriksmönstret bör du kontrollera om det finns ett verkligt behov av det. Om du ska skapa liknande typer av objekt upprepade gånger och även behöver ett lager för att skapa nya instanser med hjälp av dessa objekt samtidigt som du tillhandahåller en viss abstraktionsnivå för skapelselogiken, ja – då är fabriksmönstret ett bra alternativ
.