Աբստրակտ ֆաբրիկա (նախագծման ձևանմուշ)

Աբստրակտ ֆաբրիկա նախագծման ձևանմուշը իրենից ներկայացնում է առանձին ֆաբրիկաների ինկապսուլյացայի մեթոդ, որտեղ վերոհիշյալ ֆաբրիկաներն ունեն ընդհանուր թեմատիկա՝ առանց իրենց կոնկրետ դասերը մատնանշելու։ Սովորական օգտագործման դեպքում ծրագրային ապահովումը ստեղծում է աբստրակտ ֆաբրիկայի կոնկրետ իրականացում, իսկ այնուհետև ընդհանուր ինտերֆեյս է օգտագործում կոնկրետ օբյեկտների ստեղծման համար, որոնք որ հանդիսանում են թեմայի մաս։ Հայցողը () չգիտե, թե ինչ կոնկրետ օբյեկտներ է ստանում ամեն մի ներքին ֆաբրիկայից, քանի որ նա իր ապրանքները () ստեղծելու համար օգտագործում է ընդհանուր ինտերֆեյս։ Մոդելն առանձնացնում է իրականացման մանրամասները օբյեկտների բազմությունից և հիմնվում է օբյեկտի կոմպոզիցիայի վրա, որտեղ օբյեկտի ստեղծումը իրականացվում է ֆաբրիկայի ինտերֆեյսի մեթոդներով։

Որպես Աբստրակտ ֆաբրիկայի նմւոշ կարող է հանդիսանալ DocumentCreator դասը, որն ինտերֆեյսներ է ապահովում մի շարք արգասիքներ () (օրինակ createLetter() և createResume()) ստեղծելու համար։ Այս համակարգը կունենա ցանակացած քանակության DocumentCreator դասերի տարբերակներ, որպիսիք են FancyDocumentCreator կամ ModernDocumentCreator, որոնցից ամեն մեկն ունի createLetter() և createResume() իրականացումներ, որպեսզի ստեղծի համապատասխանաբար FancyLetter կամ ModernResume օբյեկտներ։ Այս արգասիքներից յուրաքանչյուրն հանդիսանում է պարզ աբստրակտ Letter կամ Resume դասերի տեսքով, որոնց ճանաչում է հայցողը ()։ Հայցողի կոդը կստանա DocumentCreator-ի համապատասխան օրինակ և կկանչի իր ֆաբրիկային մեթոդը։ Բոլոր ստացված օբյեկտները կիրականացվեն միևնույն DocumentCreator-ի միջոցով։ Հայցողը միայն պետք է իմանա, թե ինչպես պետք է դիմել Letter կամ Resume աբստրակտ դասերին, այլ ոչ թե ֆաբրիկային մեթոդի հատուկ տարբերակի կանչը։

Ֆաբրիկան հանդիսանում է կոնկրետ դաս ծրագրավորման կոդի մեջ, որի միջոցով ստեղծվում է օբյեկտները։ Այս նախագծման ձևանմուշի օգտագործման նպատակահարմարությունը նրանումն է, որ առանձնացնվի օբյեկտի ստեղծումը նրա օգտագործումից կամ էլ կապակցված օբյեկտների ընտանիքի ստեղծումը, որոնք կախված չեն կոնկրետ դասերից։ Դա թույլ է տալիս նոր կամայական տիպ ներմուծել կոդի մեջ առանց բազային կոդը փոփոխման ենթարկելու։

Այս ձևանմուշի օգտագործումը թույլ է տալիս տեղերով փոփոխել կոնկրետ իրականացումները առանց դրանք կանչվող կոդի փոփոխության, անգամ ծրագրի իրականացման պահին։ Այնուամենայնիվ, այս ձևանմուշի, ինչպես նաև նմանատիպ այլ նախագծման մոդելներների օգտագործումը կարող է դառնալ ավելորդ բարդության և լրացուցիչ աշխատանքի պատճառ սկզբանական կոդը կազմելիս։ Բացի այդ կոդի բարձր մակարդակի բաժանումը և աբստրակցիան կարող են համակարգը դարձնել դժվար սպասարկվող և թեսթավորվող։ Դրա համար էլ նախքան այն կիրառելը բոլոր թեր և դեմ կողմերը պետք է լրջորեն ուսումնասիրել։

Ընդհանուր հասկացողություններ 
 Client - հայցող
 Instance - նմուշ
 Implementation - իրականացում
 Product - արգասիք

Նկարագրություն 
Աբստրակտ ֆաբրիկա նախագծման ձևանմուշն ինտերֆեյս է ապահովում կապակցված ընտանիքների կամ փոխկապակցված օբյեկտների ստեղծման համար՝ առանց մատնանշելու նրանց կոնկրետ դասերը

Օգտագործումը 
Ֆաբրիկան միայն որոշում է թե ինչ կոնկրետ տիպի օբյեկտ պետք է ստեղծվի և որտեղից օբյեկտը իրականում պետք է ստեղծվի (օրինակ C++ լեզվում new օպերատորի) կիրառմամբ։ Այնուամենայնիվ, ֆաբրիկան միայն աբստրակտ ցուցիչ է վերադարձնում ստեղծված կոնկրետ օբյեկտի վրա։

Այս մեխանիզմը մեկուսացնում է հայցողի կոդը օբյեկտի ստեղծումից։ Հայցողը ֆաբրիկայից ցանկալի տիպի օբյեկտ է կանչում և ստանում է աբստրակտ ցուցիչ այդ օբյեկտի վրա։

Քանի որ ֆաբրիկան վերադարձնում է միայն աբստրակտ ցուցիչ, հայցողի կոդը (որ ֆաբրիկայից օբյեկտ է հայցել) չգիտե, թե այդ պահին կոնկրետ ինչ օբյեկտ ստեղծվեց։ Այնուամենայնիվ, կոնկրետ օբյեկտի տիպը (և, հետևաբար, կոնկրետ ֆաբրիկան) հանդիսանում է որպես աբստրակտ ֆաբրիկայի նմուշ ()։ Ֆաբրիկան այն կարող է կարդալ կոնկրետ կոնֆիգուրացիոն ֆայլից։ Մասնավորապես դա նշանակում է.
 Հայցողի կոդը ընդհանրապես կախված չէ կոնկրետ տիպից և կարիք չկա այնտեղ ներառել որևէ header file կամ էլ դաս հայտարարել։ Հայցողի կոդը գործ ունի միայն աբստրակտ տիպի հետ։ Կոնկրետ տիպի օբյեկտները իրականում ստեղծվում են ֆաբրիկայում, բայց հայցողի կոդին օբյեկտները հասանելի է միայն նրանց աբստրակտ ինտերֆեյսի միջոցով։
 Նոր կոնկրետ տիպերի ավելացումն արվում է հայցողի կոդի փոփոխմամբ՝ օգտագործելով այլ ֆաբրիկա։ Տարբեր ֆաբրիկաներ ստեղծում են տարբեր տիպերի կոնկրետ օբյեկտներ, բայց նախկինի պես վերադարձնում են նույն տիպի աբստրակտ ցուցիչ՝ մեկուսացնելով հայցողի կոդը փոփոխություններից։ Սա ավելի հեշտ է, քան հայցողի կոդի փոփոխումը, որպեսզի ստեղծվի նոր տիպի օբյեկտ, որը կպահանջեր փոփոխություններ կատարել կոդի բոլոր մասերում, որտեղ որ ստեղծվում է նոր օբյեկտը (ինչպես նաև համոզվել, որ կոդի այդ մասերում բավարար ինֆորմացիա կա նոր կոնկրետ տիպի մասին՝ ներառելով դասի header ֆայլը)։ Եթե ֆաբրիկայի օբյեկտները պահվում են որպես գլոբալ միայնակ օբյեկտ և հայցողի կոդը մի անգամ է կանչում տվյալ ֆաբրիկային օբյեկտ ստեղծելու համար, ապա ֆաբրիկայի օբյեկտի փոփոխումը նույնքան հեշտ է, որքան որ միայնակ օբյեկտի փոփոխումը։

Կառուցվածք

Խելացի դասի սխեմա 

GuiFactory ինտերֆեյսի createButton մեթոդը վերադարձնում է Button տիպի օբյեկտը։ Button օբյեկտի վերադարձի իրականացումը կախված է GuiFactory-ի կանչի մեթոդից։

UML դասի սխեմա

Պսեվդոկոդ 
Կախված թե ինչ ֆաբրիկա է օգտագործվում, պետք է պատկերել կոճակը կամ Windows կամ էլ Mac OS X ոճով։ Ուշադրություն դարձրեք, որ ծրագիրը գաղափար անգամ չունի, թե ինչ GUIFactory է կանչվում կոճակը ստեղծելու ժամանակ։

 interface Button is
  method paint()
 
 interface GUIFactory is
  method createButton()
    output:  a button
 
 class WinFactory implementing GUIFactory is
  method createButton() is
    output:  a Windows button
   Return a new WinButton
 
 class OSXFactory implementing GUIFactory is
  method createButton() is
    output:  an OS X button
   Return a new OSXButton
 
 class WinButton implementing Button is
  method paint() is
   Render a button in a Windows style
 
 class OSXButton implementing Button is
  method paint() is
   Render a button in a Mac OS X style
 
 class Application is
  constructor Application(factory) is
    input:  the GUIFactory factory used to create buttons
   Button button := factory.createButton()
   button.paint()
 
 Read the configuration file
 If the OS specified in the configuration file is Windows, then
  Construct a WinFactory
  Construct an Application with WinFactory
 else
  Construct an OSXFactory
  Construct an Application with OSXFactory

Օրինակներ

C# 
Աբստրակտ ֆաբրիկան բազային Ֆաբրիկա մոդելի ընդլայնումն է։ Այն ապահովում է Ֆաբրիկա ինտերֆեյսներ փոխկապակցված դասերի ընտանիք ստեղծելու համար։

/*IVSR:Abstract factory pattern*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.AbstractFactory
{
    public class GenericFactory<T> 
        where T : new()
    {
        public T CreateObject()
        {
            return new T();
        }
    }

    public abstract class CarFactory
    {
        public abstract SportsCar CreateSportsCar();
        public abstract FamilyCar CreateFamilyCar();
    }
    
    public abstract class FamilyCar
    {
        public abstract void Speed(SportsCar abstractFamilyCar);
    }

    public abstract class SportsCar
    {
    }

    public class MercedesFactory : CarFactory
    {
        public override SportsCar CreateSportsCar()
        {
            return new MercedesSportsCar();
        }

        public override FamilyCar CreateFamilyCar()
        {
            return new MercedesFamilyCar();
        }
    }
    
    
    class MercedesSportsCar : SportsCar
    {
    }

    class MercedesFamilyCar : FamilyCar
    {
        public override void Speed(SportsCar abstractSportsCar)
        {
            Console.WriteLine(GetType().Name + " is slower than "
                + abstractSportsCar.GetType().Name);
        }
    }

    public class Driver
    {
        private CarFactory _carFactory;
        private SportsCar _sportsCar;
        private FamilyCar _familyCar;

        public Driver(CarFactory carFactory)
        {
            CarFactory = carFactory;
            SportsCar = CarFactory.CreateSportsCar();
            FamilyCar = CarFactory.CreateFamilyCar();
        }

        private CarFactory CarFactory
        {
            get { return _carFactory; }
            set { _carFactory = value; }
        }

        private SportsCar SportsCar
        {
            get { return _sportsCar; }
            set { _sportsCar = value; }
        }

        private FamilyCar FamilyCar
        {
            get { return _familyCar; }
            set { _familyCar = value; }
        }

        public void CompareSpeed()
        {
            FamilyCar.Speed(SportsCar);
        }
    }
}

Ֆաբրիկային մեթոդը նույնպես իրականացված է ընդհանուր ինտերֆեյսից օգտվելով, և նրանցից յուրաքանչյուրը վերադարձնում է օբյեկտներ։
//IVSR: Abstract factory using common interface
public interface IFactory1
    {
        IPeople GetPeople();
    }
    public class Factory1 : IFactory1
    {
        public IPeople GetPeople()
        {
            return new Villagers();
        }
    }

    public interface IFactory2
    {
        IProduct GetProduct();
    }
    public class Factory2 : IFactory2
    {
        public IProduct GetProduct()
        {
            return new IPhone();
        }
    }

    public abstract class AbstractFactory12
    {
        public abstract IFactory1 GetFactory1();
        public abstract IFactory2 GetFactory2();
    }

    public class ConcreteFactory : AbstractFactory12
    {

        public override IFactory1 GetFactory1()
        {
            return new Factory1();
        }

        public override IFactory2 GetFactory2()
        {
            return new Factory2();
        }
    }

Ծանոթագրություններ

Արտաքին հղումներ 
 Abstract Factory  UML սխեմա + նկարագրություն

Ծրագրավորում