From Wikipedia, the free encyclopedia
Az Absztrakt gyár (angolul Abstract factory) programtervezési minta módot nyújt arra, hogy egységbe zárjuk közös témához kapcsolódó egyedi gyártó metódusok egy csoportját anélkül, hogy specifikálnák azok konkrét osztályait.[1]
Normál használatban, a kliens szoftver létrehozza az absztrakt gyár egy konkrét implementációját, és aztán a gyár általános interfészét használja a témához kapcsolódó konkrét objektumok létrehozásához. A kliens nem tudja (vagy nem törődik vele), milyen konkrét objektumokat kap ezekből a belső gyárakból, mivel csak a termékeik általános interfészét használja.[1] Ez a tervezési minta szétválasztja egymástól objektumok egy csoportjának implementációját azok általános használatától és objektum összetételre hagyatkozik, mivel az objektumok létrehozása olyan metódusokban van implementálva, amik a gyár interfészén vannak ismertté téve számára.[1]
Egy példa az absztrakt gyár mintára, egy DokumentumLétrehozó
nevű absztrakt osztály lehetne, ami interfészt nyújt többféle termék létrehozásához (pl.készítsLevelet()
és készítsÖsszefoglalót()
). A rendszerben bármennyi DokumentumLétrehozó
osztályból származtatott konkrét gyár-változat lehet, mint például DíszesDokumentumLétrehozó
vagy ModernDokumentumLétrehozó
, mindegyikük különböző implementációval a készítsLevelet()
és készítsÖsszefoglalót()
metódusokra, amik elkészítik majd a megfelelő objektumokat mint például a DíszesLevél
vagy a ModernÖsszefoglaló
. Ezeknek a termékeknek mindegyike egy-egy egyszerű absztrakt osztályból van származtatva, mint például a Levél
vagy az Összefoglaló
, amik ismertek a kliens számára. A kliens kódja egy a témának megfelelő példányt fog kapni a DokumentumLétrehozó
osztály egy származtatott konkrét osztályából, és annak a gyártó metódusait hívja majd meg. Az eredményül kapott objektumok mindegyike, ezen DokumentumLétrehozó
osztály-implementáció által kerül majd legyártásra, amik megfelelnek majd a közös témának (például mindannyian „Díszes” vagy „Modern” objektumok lesznek). A kliensnek csak annyit kell tudnia, hogy hogyan kezelje az absztrakt Levél
vagy Összefoglaló
osztályokat, nem kell ismernie a specifikus változatokat, amiket a konkrét gyártól kapott.[2]
Egy gyár, egy konkrét osztály helye a kódban, ahol az objektumok létrejönnek. Az absztrakt gyár minta használatának szándéka arra irányul, hogy elszigetelje egymástól az objektumok létrehozását azok használatától, és hogy egymással összefüggő objektumok családjait hozza létre anélkül, hogy azok konkrét osztályaitól függene.[1] Ez lehetővé teszi új származtatott típusok bevezetését, anélkül, hogy az ős osztályokat használó kódot meg kellene változtatni.
Ennek a mintának a használata, lehetővé teszi egy rendszerben a konkrét típus implementációk kicserélését (még akár futásidőben is) anélkül, hogy az őket használó kódot módosítanánk. Mindazonáltal ennek a mintának (és a hasonló programtervezési mintáknak) a használata, szükségtelen komplexitást okozhat, és plusz munkát igényelhet a kezdeti kódkészítésben. Továbbá az absztrakció és a szétválasztás magasabb szintje olyan rendszert eredményezhet, amiben nehezebb a hibakeresés és a karbantartás.
Az Absztrakt gyár minta lényege, hogy „Interfészt adjon ahhoz, hogy egymással összefüggő objektumok családjait hozzuk létre anélkül, hogy specifikálnánk a konkrét osztályaikat.”.[3]
A gyár határozza meg a létrehozásra kerülő objektum tényleges konkrét típusát, és a gyár az a hely ahol az objektum ténylegesen létrejön (például a C++ nyelven, a new művelettel). Mindazonáltal, a gyár csak egy absztrakt mutatót (pointert) ad vissza, ami a létrehozott konkrét objektumra mutat.
Ez elszigeteli a klienst az objektum létrehozástól azáltal, hogy a kliensnek meg kell kérnie egy gyár objektumot, hogy készítse el az általa kívánt absztrakt típust és adjon vissza számára egy absztrakt mutatót az objektumra.[4]
Mivel a gyár csak egy absztrakt mutatót (pointert) ad vissza, a kliens kód (ami az objektumot kérte a gyártól) nem ismeri az éppen létrehozott objektum aktuális, konkrét típusát. Mindazonáltal az absztrakt gyár ismeri a konkrét objektum típusát (ennélfogva a konkrét gyárat is); például az absztrakt gyár beolvashatja ezeket az adatokat egy konfigurációs fájlból. A kliensnek így nem kell típust specifikálnia, mivel az már megadásra került a konfigurációs fájlban. Részleteiben ez a következőt jelenti:
A createButton
függvény a GuiFactory
interfészben Button
típusú objektumokat ad vissza. Az, hogy a Button
objektumnak milyen konkrét implementációja kerül visszaadásra, a GuiFactory
osztály implementációján múlik, ami a függvényhívást kezeli.
A kód egy gombot (Button) készít, amely Windows vagy Mac OS X stílusú lehet, attól függően, hogy melyik gyárat használjuk. Vegyük észre, hogy az alkalmazásnak (Application) semmilyen tudomása nincs arról, hogy milyen „GuiFactory” gyár van számára megadva (mi a konkrét implementációja), mint ahogy arról sem, hogy az konkrétan milyen gombot (Button) gyárt.
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
Az Absztrakt gyár az alap Gyár minta bővítése. Gyár interfészeket nyújt egymással összetartozó osztályok gyártásához. Más szavakkal, interfészeket deklarálok a Gyárakhoz, amiket aztán hasonló módon használok mint az alap Gyár mintánál.
/*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 abstractSportsCar);
}
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();
}
public CarFactory CarFactory
{
get { return _carFactory; }
set { _carFactory = value; }
}
public SportsCar SportsCar
{
get { return _sportsCar; }
}
public FamilyCar FamilyCar
{
get { return _familyCar; }
}
public void CompareSpeed()
{
FamilyCar.Speed(SportsCar);
}
}
}
A gyártó metódusok szintén egy közös interfész alapján vannak implementálva, melyek mindegyike objektumokat ad vissza.
//IVSR: Abstract factory using common interface
public interface IPeopleFactory
{
IPeople GetPeople();
}
public class VillagersFactory : IPeopleFactory
{
public IPeople GetPeople()
{
return new Villagers();
}
}
public interface IProductFactory
{
IProduct GetProduct();
}
public class AppleFactory : IProductFactory
{
public IProduct GetProduct()
{
return new IPhone();
}
}
public abstract class AbstractFactory
{
public abstract IPeopleFactory GetPeopleFactory();
public abstract IProductFactory GetProductFactory();
}
public class ConcreteFactory : AbstractFactory
{
public override IPeopleFactory GetPeopleFactory()
{
return new VillagersFactory ();
}
public override IProductFactory GetProductFactory()
{
return new AppleFactory ();
}
}
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.