Abstrakt fabrik (designmönster)
Den aktuella versionen av sidan har ännu inte granskats av erfarna bidragsgivare och kan skilja sig väsentligt från
versionen som granskades den 2 mars 2018; kontroller kräver
25 redigeringar .
Abstrakt fabrik |
---|
abstrakt fabrik |
Sorts |
alstrande |
Ändamål |
Ger ett gränssnitt för att skapa familjer av relaterade eller beroende av varandra utan att specificera deras konkreta klasser. |
Strukturera |
|
Gäller i ärenden |
- När programmet måste vara oberoende av processen och typer av nya objekt som skapas.
- När det är nödvändigt att skapa familjer eller grupper av inbördes relaterade objekt, exklusive möjligheten till samtidig användning av objekt från dessa olika uppsättningar i samma sammanhang [1] .
|
fördelar |
- isolerar specifika klasser;
- förenklar utbytet av produktfamiljer;
- garanterar produktkompatibilitet.
|
Minus |
- det är svårt att lägga till stöd för en ny typ av produkt.
|
Beskrivs i Design Patterns |
Ja |
En abstrakt fabrik är ett generativt designmönster som ger ett gränssnitt för att skapa familjer av sammanhängande eller beroende av varandra utan att specificera deras konkreta klasser. Mönstret implementeras genom att skapa en abstrakt klass Factory, som är ett gränssnitt för att skapa systemkomponenter (till exempel för ett fönstergränssnitt kan det skapa fönster och knappar). Sedan skrivs klasser som implementerar detta gränssnitt [2] .
Utnämning
Ger ett gränssnitt för att skapa familjer av relaterade eller beroende av varandra utan att specificera deras konkreta klasser.
Implementering
Fördelar
- isolerar specifika klasser;
- förenklar utbytet av produktfamiljer;
- garanterar produktkompatibilitet.
Nackdelar
- det är svårt att lägga till stöd för en ny typ av produkt.
Applikation
- Systemet ska inte vara beroende av hur objekten som ingår i det skapas, sätts ihop och presenteras.
- Relaterade objekt i en samling måste användas tillsammans, och du måste tillämpa denna begränsning.
- Systemet måste konfigureras av en av familjerna av dess ingående objekt.
- Det krävs att det tillhandahålls ett bibliotek med objekt som endast exponerar deras gränssnitt, inte deras implementering.
Exempel
Snabbexempel
Swift källkod
//: Lekplats - substantiv: en plats där människor kan leka
/// <sammanfattning>
/// Abstrakt fabriksklass
/// </summary>
protokoll AbstractFactory {
func createProductA () -> AbstractProductA
func createProductB () -> AbstractProductB
}
/// <sammanfattning>
/// Fabriksklass #1
/// </summary>
klass ConcreteFactory1 : AbstractFactory {
public func createProductA () -> AbstractProductA {
return ProductA1 ()
}
public func createProductB () -> AbstractProductB {
return ProductB1 ()
}
}
/// <sammanfattning>
/// Fabriksklass #2
/// </summary>
klass ConcreteFactory2 : AbstractFactory {
public func createProductA () -> AbstractProductA {
return ProductA2 ()
}
public func createProductB () -> AbstractProductB {
return ProductB2 ()
}
}
/// <summary>
/// Abstrakt produktklass A
/// </summary>
protokoll AbstractProductA {}
//
/// <summary>
/// Abstrakt produktklass B
/// </summary>
protokoll AbstractProductB {
func interagera ( a : AbstractProductA )
}
/// <summary>
/// Första produktklassen av typ A
/// </summary>
klass ProductA1 : AbstractProductA {}
/// <summary>
/// Första produktklassen av typ B
/// </summary>
class ProductB1 : AbstractProductB {
public func interact ( a : AbstractProductA ) {
print ( " \( type ( of : self )) interacts with \ ( typ ( av : a . själv )) " )
}
}
/// <summary>
/// Andra produktklassen av typ A
/// </summary>
klass ProductA2 : AbstractProductA {}
/// <summary>
/// Andra produktklassen av typ B
/// </summary>
class ProductB2 : AbstractProductB {
public func interact ( a : AbstractProductA ) {
print ( " \( type ( of : self )) interacts with \ ( typ ( av : a . själv )) " )
}
}
/// <summary>
/// Klientklassen där interaktionen mellan objekt sker
/// </summary>
class Client {
private let _abstractProductA : AbstractProductA
private let _abstractProductB : AbstractProductB
// Konstruktör
public init ( fabrik : AbstractFactory ) {
_abstractProductB = fabrik . createProductB ();
_abstractProductA = fabrik . createProductA ();
}
public func run () {
_abstractProductB . interagera ( a : _abstractProductA )
}
}
/// <sammanfattning>
/// Applikationsstartpunkt
/// </summary>
// Anropar abstrakt fabrik #1
let factory1 = ConcreteFactory1 ()
let client1 = Client ( factory : factory1 )
client1 . springa ()
// Ring abstrakt fabrik #2
låt fabrik2 = ConcreteFactory2 ()
låt klient2 = Klient ( fabrik : fabrik2 )
klient2 . springa ()
Exempel i C# [3]
Källkod i
C Sharp
använder System ;
namnutrymme DoFactory.GangOfFour.Abstract.Structural
{
class MainApp
{
/// <summary>
/// Applikationsstartpunkt
/// </summary>
public static void Main ()
{
// Abstrakt fabriksanrop #1
AbstractFactory factory1 = new ConcreteFactory1 ();
Klient klient1 = ny klient ( fabrik1 );
klient1 . köra ();
// Ring abstrakt fabrik #2
AbstractFactory factory2 = new ConcreteFactory2 ();
Klient klient2 = ny klient ( fabriks2 );
klient2 . köra ();
// Väntar på input
Console . ReadKey ();
}
}
/// <summary>
/// Abstrakt fabriksklass
/// </summary>
abstrakt klass AbstractFactory
{
public abstract AbstractProductA CreateProductA ();
public abstract AbstractProductB CreateProductB ();
}
/// <summary>
/// Fabriksklass #1
/// </summary>
class ConcreteFactory1 : AbstractFactory
{
public override AbstractProductA CreateProductA ()
{
return new ProductA1 ();
}
public override AbstractProductB CreateProductB ()
{
returnera ny produktB1 ();
}
}
/// <summary>
/// Fabriksklass #2
/// </summary>
class ConcreteFactory2 : AbstractFactory
{
public override AbstractProductA CreateProductA ()
{
return new ProductA2 ();
}
public override AbstractProductB CreateProductB ()
{
returnera ny produktB2 ();
}
}
/// <summary>
/// Abstrakt produktklass A
/// </summary>
abstrakt klass AbstractProductA
{
}
/// <sammanfattning>
/// Abstrakt produktklass B
/// </summary>
abstrakt klass AbstractProductB
{
public abstract void Interact ( AbstractProductA a );
}
/// <summary>
/// Första produktklassen av typ A
/// </summary>
klass ProductA1 : AbstractProductA
{
}
/// <summary>
/// Första produktklassen av typ B
/// </summary>
klass ProductB1 : AbstractProductB
{
public override void Interact ( AbstractProductA a )
{
Console . WriteLine ( denna . GetType (). Name +
" interagerar med " + a . GetType (). Name );
}
}
/// <summary>
/// Andra produktklassen av typ A
/// </summary>
klass ProductA2 : AbstractProductA
{
}
/// <summary>
/// Andra produktklassen av typ B
/// </summary>
class ProductB2 : AbstractProductB
{
public override void Interact ( AbstractProductA a )
{
Console . WriteLine ( denna . GetType (). Name +
" interagerar med " + a . GetType (). Name );
}
}
/// <summary>
/// Klientklassen där interaktionen mellan objekt sker
/// </summary>
class Client
{
private AbstractProductA _abstractProductA ;
privat AbstractProductB _abstractProductB ;
// Konstruktör
offentlig klient ( AbstractFactory factory )
{
_abstractProductB = factory . CreateProductB ();
_abstractProductA = fabrik . CreateProductA ();
}
public void Kör ()
{
_abstractProductB . Interagera ( _abstractProductA );
}
}
}
Java-exempel
Java -källa
public class AbstractFactoryExample {
public static void main ( String [] args ) {
AbstractFactory factory1 = new ConcreteFactory1 ();
Klient klient1 = ny klient ( fabrik1 );
klient1 . exekvera ();
AbstractFactory factory2 = new ConcreteFactory2 ();
Klient klient2 = ny klient ( fabriks2 );
klient2 . exekvera ();
}
}
class Client {
private AbstractProductA productA ;
privat Sammanfattning ProduktB produktB ;
Klient ( AbstractFactory factory ) {
productA = factory . createProductA ();
produktB = fabrik . createProductB ();
}
void execute () {
produktB . interagera ( produktA );
}
}
gränssnitt AbstractFactory {
AbstractProductA createProductA ();
AbstractProductB createProductB ();
}
gränssnitt AbstractProductA {
void interact ( AbstractProductB b );
}
gränssnitt AbstractProductB {
void interact ( AbstractProductA a );
}
klass ConcreteFactory1 implementerar AbstractFactory {
@Override
public AbstractProductA createProductA () {
returnera ny ProductA1 ();
}
@Override
public AbstractProductB createProductB () {
return new ProductB1 ();
}
}
klass ConcreteFactory2 implementerar AbstractFactory {
@Override
public AbstractProductA createProductA () {
returnera ny ProductA2 ();
}
@Override
public AbstractProductB createProductB () {
returnera ny produktB2 ();
}
}
klass ProductA1 implementerar AbstractProductA {
@Override
public void interact ( AbstractProductB b ) {
System . ut . println ( denna . getClass (). getName () + " interagerar med " + b . getClass (). getName ());
}
}
klass ProductB1 implementerar AbstractProductB {
@Override
public void interact ( AbstractProductA a ) {
System . ut . println ( denna . getClass (). getName () + " interagerar med " + en . getClass (). getName ());
}
}
klass ProductA2 implementerar AbstractProductA {
@Override
public void interact ( AbstractProductB b ) {
System . ut . println ( denna . getClass (). getName () + " interagerar med " + b . getClass (). getName ());
}
}
class ProductB2 implementerar AbstractProductB {
@Override
public void interact ( AbstractProductA a ) {
System . ut . println ( denna . getClass (). getName () + " interagerar med " + en . getClass (). getName ());
}
}
PHP5 exempel
PHP5 källkod
gränssnitt IHead
{
public function drawHead ( $x , $y );
}
class RedHead implementerar IHead
{
public function drawHead ( $x , $y ) {
echo 'Ditt röda huvud i axeln x = ' . $x . ' och axeln y = ' . $y . '</br>' . PHP_EOL ;
}
}
klass WhiteHead implementerar IHead
{
public function drawHead ( $x , $y ) {
echo 'Ditt vita huvud i axeln x = ' . $x . ' och axeln y = ' . $y . '</br>' . PHP_EOL ;
}
}
gränssnitt IBody
{
public function drawBody ( $x , $y );
}
class RedBody implementerar IBody
{
public function drawBody ( $x , $y ) {
echo 'Din röda kropp i axeln x = ' . $x . ' och axeln y = ' . $y . '</br>' . PHP_EOL ;
}
}
class WhiteBody implementerar IBody
{
public function drawBody ( $x , $y ) {
echo 'Din vita kropp i axeln x = ' . $x . ' och axeln y = ' . $y . '</br>' . PHP_EOL ;
}
}
/**
* Interface ISnowman - detta är abstrakt fabrik
*/
interface ISnowman
{
public function drawHead ( $x , $y );
public function drawBody ( $x , $y );
}
/**
* Klass WhiteSnowman - betongfabrik
*/
klass WhiteSnowman implementerar ISnowman
{
protected $head ;
skyddad $kropp ;
public function __construct () {
$this -> head = new WhiteHead ();
$this -> body = new WhiteBody ();
}
public function drawHead ( $x , $y ) {
$this -> head -> drawHead ( $x , $y );
}
public function drawBody ( $x , $y ) {
$this -> body -> drawBody ( $x , $y );
}
}
/**
* Klass RedSnowman - betongfabrik
*/
klass RedSnowman implementerar ISnowman
{
protected $head ;
skyddad $kropp ;
public function __construct () {
$this -> head = new RedHead ();
$this -> body = new RedBody ();
}
public function drawHead ( $x , $y ) {
$this -> head -> drawHead ( $x , $y );
}
public function drawBody ( $x , $y ) {
$this -> body -> drawBody ( $x , $y );
}
}
function snowman ( ISnowman $ snowman ) {
$snowman -> drawHead ( 1 , 1 );
$snögubbe -> drawBody ( 1 , 2 );
}
$typeSnowman = 'röd' ;
// vi väljer familjetypen i början av koden
om ( $typeSnowman == 'red' )
$snowman = new RedSnowman ();
else
$snögubbe = ny WhiteSnowman ();
snögubbe ( $snögubbe );
Python-exempel
Källkod i
Python
från abc import ABCMeta , abstraktmetod
klass Öl ( metaklass = ABCMeta ):
godkänt
klass Snack ( metaklass = ABCMeta ):
@abstractmethod
def interagera ( själv , öl : Öl ) -> Inga :
godkänt
klass AbstractShop ( metaklass = ABCMeta ):
@abstractmethod
def buy_beer ( self ) -> Beer :
pass
@abstractmethod
def buy_snack ( self ) -> Snack :
pass
klass Tuborg ( Öl ):
pass
klass Staropramen ( Öl ):
pass
klass jordnötter ( mellanmål ):
def interagera ( själv , öl : Öl ) -> Inget :
print ( 'Vi drack en flaska öl {} och åt den med jordnötter' . format (
öl . __klass__ . __namn__ ))
klass Chips ( Snack ):
def interagera ( själv , öl : Öl ) -> Inget :
print ( 'Vi drack några öl {} och åt en påse chips' . format (
öl . __klass__ . __namn__ ))
klass ExpensiveShop ( AbstractShop ):
def buy_beer ( self ) -> Beer :
return Tuborg ()
def buy_snack ( self ) -> Snack :
return Peanuts ()
klass CheapShop ( AbstractShop ):
def buy_beer ( self ) -> Beer :
return Staropramen ()
def buy_snack ( self ) -> Snack :
returnera chips ()
if __name__ == '__main__' :
dyr_butik = Dyr Butik ( )
cheap_shop = Billig Butik ()
skriv ut ( 'OUTPUT:' )
öl = dyr_butik . köpa_öl ()
mellanmål = billig_butik . köpa_mellanmål ()
mellanmål . interagera ( öl )
öl = billig_butik . köpa_öl ()
mellanmål = dyr_butik . köpa_mellanmål ()
mellanmål . interagera ( öl )
'''
UTGÅNG:
Vi drack några burkar Tuborg öl och åt en påse chips
Vi drack en flaska Staropramen öl och bet den med jordnötter
'''
Scala exempel
Scala källkod
abstrakt klass AbstraktTerrestrialAnimal {
def walk : String
}
abstrakt klass _ _
def simma : String
_
abstrakt klass _ _
def getCity : String
def getTerrestrialAnimal : AbstractTerrestrialAnimal
def getWaterAnimal : AbstractWaterAnimal
}
klass Wolverine förlänger AbstractTerrestrialAnimal {
override def walk : String = "Wolverine går"
}
klass HoneyBadger utökar AbstractTerrestrialAnimal {
override def walk : String = "Honey grävling går"
}
klass Walrus utökar AbstractWaterAnimal {
override def sim : String = "Valross simmar"
}
klass SeaLion utökar AbstractWaterAnimal {
åsidosätta def simma : String = "Sjölejon simmar"
}
klass MunichZoo utökar AbstractZoo {
åsidosätt def getCity : String = "München"
åsidosätt def getTerrestrialAnimal : AbstractTerrestrialAnimal = ny Wolverine
override def getWaterAnimal : AbstractWaterAnimal = new Walrus
}
klass CapeTownZoo utökar AbstractZoo {
åsidosätt def getCity : String = "CapeTown"
åsidosätt def getTerrestrialAnimal : AbstractTerrestrialAnimal = ny HoneyBadger
override def getWaterAnimal : AbstractWaterAnimal = new SeaLion
}
objekt AbstractFactoryTest {
privat def testZoo ( zoo : AbstractZoo ): Enhet = {
println ( s"Zoo of ${ zoo . getCity } :" )
println ( zoo . getTerrestrialAnimal . walk )
println ( zoo . getWaterAnimal . swim )
}
def main ( args : Array [ String ]) Unit = {
testZoo ( new CapeTownZoo )
testZoo ( new MunichZoo )
}
}
Gå exempel
Källkod i
Go
huvudpaket _
importera "fmt"
typ Unit interface {
What () string
}
typ Action interface {
What () string
}
typ Placera gränssnitt {
Vad () sträng
}
typ TransportFactory -gränssnitt {
MakeUnit () Unit
MakeAction () Action
MakePlace () Place
}
typ Car struct {}
func ( self Car ) Vad () string {
return "car"
}
typ Ride struct {}
func ( self Ride ) What () string {
return "ride"
}
skriv vägstruktur { }
func ( self Road ) Vad () sträng {
return "road"
}
typ LandTransportFactory struct {}
func ( self LandTransportFactory ) MakeUnit () Enhet {
retur & bil {}
}
func ( self LandTransportFactory ) MakeAction () Action {
return & Ride {}
}
func ( self LandTransportFactory ) MakePlace () Plats {
retur & väg {}
}
typ Båtstruktur { }
func ( self Boat ) Vad () string {
return "boat"
}
typ Sail struct {}
func ( self Sail ) Vad () string {
return "sail"
}
typ Sea struct {}
func ( self Sea ) Vad () string {
returnera "hav"
}
typ SeaTransportFactory struct {}
func ( self SeaTransportFactory ) MakeUnit ( ) Enhet {
retur & båt {}
}
func ( self SeaTransportFactory ) MakeAction () Action {
return & Sail {}
}
func ( self SeaTransportFactory ) MakePlace () Placera {
return & Sea {}
}
func action ( fabrik TransportFactory ) {
enhet := fabrik . MakeUnit ()
unit_action := fabrik . MakeAction ()
plats := fabrik . MakePlace ()
fmt . Printf ( "%s %ss över %s.\n" ,
enhet . What (), unit_action . What (), place . What ())
}
func main () {
action ( & LandTransportFactory {})
action ( & SeaTransportFactory {})
}
Slutsats
Bilen åker över vägen.
Båten seglar över havet.
Ruby exempel
Ruby källkod
modul AbstractFactoryPattern
# Tillhandahålla ett gränssnitt för att skapa familjer av relaterade eller objekt utan att specificera deras konkreta klasser
# Abstrakt Factory
class WarriorFactory
def create_knight
raise NotImplementedError
end
def create_archer
höj NotImplementedError
end
end
#
Betongfabriksklass OrcWarriorFactory < WarriorFactory
def create_knight
OrcKnight . nytt
slut
def create_archer
OrcArcher . nytt
slutslut
_
#
Betongfabriksklass ElfWarriorFactory < WarriorFactory
def create_knight
ElfKnight . nytt
slut
def create_archer
ElfArcher . nytt
slutslut
_
# Abstrakt
produktklass Knight def inspect self . klass . namn . dela ( '::' ) . sista slutet _
# Abstrakt
produktklass Archer def inspect self . klass . namn . dela ( '::' ) . sista slutet _
#
Produktklass OrcKnight < Knight
end
#
Produktklass ElfKnight < Knight
end
#
Produktklass OrcArcher < Archer
end
#
Produktklass ElfArcher < Archer
end
# Klientklass
Army def
initialisera ( fabrik ) @knights
= [ ]
3 . gånger { @knights << fabrik . create_knight }
@bågskyttar = []
3 . gånger { @archers << fabrik . create_archer }
slut
def inspect
"Knights #{ @knights . map ( & :inspect ) } Archers #{ @archers . map ( & :inspect ) } "
end
end
def själv . kör
orcher = Armé . new ( OrcWarriorFactory . new )
sätter "Orcs army: #{ orcs . inspect } "
tomtar = armé . new ( ElfWarriorFactory . new )
sätter "Elves army: #{ elves . inspect } "
end
end
AbstractFactoryPattern . springa
# Orcs armé: Knights ["OrcKnight", "OrcKnight", "OrcKnight"] Archers ["OrcArcher", "OrcArcher", "OrcArcher"]
# Alverarmé: Knights ["ElfKnight", "ElfKnight", "ElfKnight"] Archers ["ElfArcher", "ElfArcher", "ElfArcher"]
Litteratur
- E. Gamma, R. Helm, R. Johnson, J. Vlissides . Tekniker för objektorienterad design. Designmönster = Designmönster: Element av återanvändbar objektorienterad programvara. - St Petersburg. : "Peter" , 2007. - S. 366. - ISBN 978-5-469-01136-1 . (även ISBN 5-272-00355-1 )
Länkar
Anteckningar
- ↑ Abstrakt fabriksmönster . Hämtad 14 juni 2013. Arkiverad från originalet 14 juni 2013. (obestämd)
- ↑ Generera mönster: Abstrakt fabrik . Hämtad 14 juni 2013. Arkiverad från originalet 14 juni 2013. (obestämd)
- ↑ Abstrakt Factory .NET-designmönster i C# och VB - dofactory.com . www.dofactory.com Datum för åtkomst: 3 mars 2016. Arkiverad från originalet 3 mars 2016. (obestämd)