Предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретных классов.
Структура
Применяется в случаях
Когда программа должна быть независимой от процесса и типов создаваемых новых объектов.
Когда необходимо создать семейства или группы взаимосвязанных объектов исключая возможность одновременного использования объектов из разных этих наборов в одном контексте[1].
Абстрактная фабрика (англ.Abstract factory) — порождающий шаблон проектирования, предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретных классов. Шаблон реализуется созданием абстрактного класса Factory, который представляет собой интерфейс для создания компонентов системы (например, для оконного интерфейса он может создавать окна и кнопки). Затем пишутся классы, реализующие этот интерфейс[2].
importkotlin.random.Random// next interfaces are products of abstract factoriesinterfaceExecutorinterfaceLegislatorinterfaceJudge// just wrapper for governmentdataclassGovernor(valname:String,valexecutor:Executor,vallegislator:Legislator,valjudge:Judge){funwork(){println("Government $name is working!")println("Legislator $legislator set the Law")println("Executor $executor catch all criminals by the legislator laws")println("Judge $judge has sentenced all criminals to punishment")}}// abstract factory interfaceinterfaceGovernmentFactory{funcreateExecutor():ExecutorfuncreateJudge():JudgefuncreateLegislator():Legislator/** * Template Method Pattern */funcreateGovernment(name:String):Governor{returnGovernor(name,createExecutor(),createLegislator(),createJudge())}}dataclassMonarch(valname:String):Judge,Executor,Legislator// implementation of abstract factoryobjectRussianMonarchyFactory:GovernmentFactory{privatevalivanGrozny=Monarch("Иван Грозный")overridefuncreateExecutor():Executor{returnivanGrozny}overridefuncreateJudge():Judge{returnivanGrozny}overridefuncreateLegislator():Legislator{returnivanGrozny}}dataclassPresidentCandidate(valname:String,privatevalmyJudgeGuy:Judge):Executor{funsetJudge():Judge{returnmyJudgeGuy}}privatevalCONGRESS_MEMBER_COUNT=535dataclassCongress(valrepublicans:Int,valdemocrats:Int=CONGRESS_MEMBER_COUNT-republicans):LegislatorclassAmericanElectorate(privatevalpresidentCandidates:List<PresidentCandidate>){funchoosePresident():PresidentCandidate{returnpresidentCandidates.random()// here should be logic of choosing the president}funchooseParliament():Legislator{valdelta=Random.nextInt(15)returnCongress(CONGRESS_MEMBER_COUNT/2-delta)}}// implementation of abstract factoryclassPresidentRepublicFactory(privatevalelectorate:AmericanElectorate,privatevarcurrentPresident:PresidentCandidate):GovernmentFactory{overridefuncreateExecutor():Executor{currentPresident=electorate.choosePresident()returncurrentPresident}overridefuncreateJudge():Judge{returncurrentPresident.setJudge()}overridefuncreateLegislator():Legislator{returnelectorate.chooseParliament()}}dataclassElectivePerson(valname:String):Judge,ExecutordataclassParliament(valdescription:String,// left, centrist or right partiesvalpresident:ElectivePerson,valjudge:Judge):LegislatorclassEuropeanElectorate(valpeople:List<ElectivePerson>){funchooseParliament():Parliament{returnParliament(listOf("left","centrist","right").random(),people.random(),people.random())}}// implementation of abstract factoryclassParliamentRepublicFactory(privatevalelectorate:EuropeanElectorate,privatevarelectedParliament:Parliament):GovernmentFactory{overridefuncreateExecutor():Executor{returnelectedParliament.president}overridefuncreateJudge():Judge{returnelectedParliament.judge}overridefuncreateLegislator():Legislator{electedParliament=electorate.chooseParliament()returnelectedParliament}/** * should be overridden because we should select parliament firstly */overridefuncreateGovernment(name:String):Governor{valparliament=createLegislator()returnGovernor(name,createExecutor(),parliament,createJudge())}}funmain(){valbiden=PresidentCandidate("Biden",ElectivePerson("Kamalla Harris"))valamericanElectorate=AmericanElectorate(listOf(biden,PresidentCandidate("Trump",ElectivePerson("Obama"))))valeuropeanElectorate=EuropeanElectorate(listOf(ElectivePerson("Boris Johnson"),ElectivePerson("Princess Diane"),ElectivePerson("Jack Shirak"),ElectivePerson("Viktor Orban"),ElectivePerson("Floda Reltih"),ElectivePerson("Green Sky"),))//set abstract factory of governments to countriesmapOf("Rus"toRussianMonarchyFactory,"USA"toPresidentRepublicFactory(americanElectorate,biden),"Deutschland"toParliamentRepublicFactory(europeanElectorate,Parliament("Communists",ElectivePerson("Climate Liar"),ElectivePerson("War Criminal"),))).map{(country,govFactory)->govFactory.createGovernment(country)// create governments}.forEach{it.work()// enforce them to work}}
//: Playground - noun: a place where people can play/// <summary>/// Класс абстрактной фабрики/// </summary>protocolAbstractFactory{funccreateProductA()->AbstractProductAfunccreateProductB()->AbstractProductB}/// <summary>/// Класс фабрики № 1/// </summary>classConcreteFactory1:AbstractFactory{publicfunccreateProductA()->AbstractProductA{returnProductA1()}publicfunccreateProductB()->AbstractProductB{returnProductB1()}}/// <summary>/// Класс фабрики № 2/// </summary>classConcreteFactory2:AbstractFactory{publicfunccreateProductA()->AbstractProductA{returnProductA2()}publicfunccreateProductB()->AbstractProductB{returnProductB2()}}/// <summary>/// Абстрактный класс продукта А/// </summary>protocolAbstractProductA{}///// <summary>/// Абстрактный класс продукта В/// </summary>protocolAbstractProductB{funcinteract(a:AbstractProductA)}/// <summary>/// Первый класс продукта типа А/// </summary>classProductA1:AbstractProductA{}/// <summary>/// Первый класс продукта типа В/// </summary>classProductB1:AbstractProductB{publicfuncinteract(a:AbstractProductA){print("\(type(of:self)) interacts with \(type(of:a.self))")}}/// <summary>/// Второй класс продукта типа А/// </summary>classProductA2:AbstractProductA{}/// <summary>/// Второй класс продукта типа В/// </summary>classProductB2:AbstractProductB{publicfuncinteract(a:AbstractProductA){print("\(type(of:self)) interacts with \(type(of:a.self))")}}/// <summary>/// Класс клиента, в котором происходит взаимодействие между объектами/// </summary>classClient{privatelet_abstractProductA:AbstractProductAprivatelet_abstractProductB:AbstractProductB// Конструкторpublicinit(factory:AbstractFactory){_abstractProductB=factory.createProductB();_abstractProductA=factory.createProductA();}publicfuncrun(){_abstractProductB.interact(a:_abstractProductA)}}/// <summary>/// Точка входа в приложение/// </summary>// Вызов абстрактной фабрики № 1letfactory1=ConcreteFactory1()letclient1=Client(factory:factory1)client1.run()// Вызов абстрактной фабрики № 2letfactory2=ConcreteFactory2()letclient2=Client(factory:factory2)client2.run()
usingSystem;namespaceDoFactory.GangOfFour.Abstract.Structural{classMainApp{publicstaticvoidMain(){AbstractFactoryfactory1=newConcreteFactory1();Clientclient1=newClient(factory1);client1.Run();AbstractFactoryfactory2=newConcreteFactory2();Clientclient2=newClient(factory2);client2.Run();Console.ReadKey();}}abstractclassAbstractFactory{publicabstractAbstractProductACreateProductA();publicabstractAbstractProductBCreateProductB();}classConcreteFactory1:AbstractFactory{publicoverrideAbstractProductACreateProductA(){returnnewProductA1();}publicoverrideAbstractProductBCreateProductB(){returnnewProductB1();}}classConcreteFactory2:AbstractFactory{publicoverrideAbstractProductACreateProductA(){returnnewProductA2();}publicoverrideAbstractProductBCreateProductB(){returnnewProductB2();}}abstractclassAbstractProductA{}abstractclassAbstractProductB{publicabstractvoidInteract(AbstractProductAa);}classProductA1:AbstractProductA{}classProductB1:AbstractProductB{publicoverridevoidInteract(AbstractProductAa){Console.WriteLine(this.GetType().Name+" interacts with "+a.GetType().Name);}}classProductA2:AbstractProductA{}classProductB2:AbstractProductB{publicoverridevoidInteract(AbstractProductAa){Console.WriteLine(this.GetType().Name+" interacts with "+a.GetType().Name);}}classClient{privateAbstractProductA_abstractProductA;privateAbstractProductB_abstractProductB;publicClient(AbstractFactoryfactory){_abstractProductB=factory.CreateProductB();_abstractProductA=factory.CreateProductA();}publicvoidRun(){_abstractProductB.Interact(_abstractProductA);}}}
publicclassAbstractFactoryExample{publicstaticvoidmain(String[]args){AbstractFactoryfactory1=newConcreteFactory1();Clientclient1=newClient(factory1);client1.execute();AbstractFactoryfactory2=newConcreteFactory2();Clientclient2=newClient(factory2);client2.execute();}}classClient{privateAbstractProductAproductA;privateAbstractProductBproductB;Client(AbstractFactoryfactory){productA=factory.createProductA();productB=factory.createProductB();}voidexecute(){productB.interact(productA);}}interfaceAbstractFactory{AbstractProductAcreateProductA();AbstractProductBcreateProductB();}interfaceAbstractProductA{voidinteract(AbstractProductBb);}interfaceAbstractProductB{voidinteract(AbstractProductAa);}classConcreteFactory1implementsAbstractFactory{@OverridepublicAbstractProductAcreateProductA(){returnnewProductA1();}@OverridepublicAbstractProductBcreateProductB(){returnnewProductB1();}}classConcreteFactory2implementsAbstractFactory{@OverridepublicAbstractProductAcreateProductA(){returnnewProductA2();}@OverridepublicAbstractProductBcreateProductB(){returnnewProductB2();}}classProductA1implementsAbstractProductA{@Overridepublicvoidinteract(AbstractProductBb){System.out.println(this.getClass().getName()+" interacts with "+b.getClass().getName());}}classProductB1implementsAbstractProductB{@Overridepublicvoidinteract(AbstractProductAa){System.out.println(this.getClass().getName()+" interacts with "+a.getClass().getName());}}classProductA2implementsAbstractProductA{@Overridepublicvoidinteract(AbstractProductBb){System.out.println(this.getClass().getName()+" interacts with "+b.getClass().getName());}}classProductB2implementsAbstractProductB{@Overridepublicvoidinteract(AbstractProductAa){System.out.println(this.getClass().getName()+" interacts with "+a.getClass().getName());}}
interfaceIHead{publicfunctiondrawHead($x,$y);}classRedHeadimplementsIHead{publicfunctiondrawHead($x,$y){echo'Your red head in axis x = '.$x.' and axis y = '.$y.'</ br>'.PHP_EOL;}}classWhiteHeadimplementsIHead{publicfunctiondrawHead($x,$y){echo'Your white head in axis x = '.$x.' and axis y = '.$y.'</ br>'.PHP_EOL;}}interfaceIBody{publicfunctiondrawBody($x,$y);}classRedBodyimplementsIBody{publicfunctiondrawBody($x,$y){echo'Your red body in axis x = '.$x.' and axis y = '.$y.'</ br>'.PHP_EOL;}}classWhiteBodyimplementsIBody{publicfunctiondrawBody($x,$y){echo'Your white body in axis x = '.$x.' and axis y = '.$y.'</ br>'.PHP_EOL;}}/** * Interface ISnowman - this is abstract factory */interfaceISnowman{publicfunctiondrawHead($x,$y);publicfunctiondrawBody($x,$y);}/** * Class WhiteSnowman - concrete factory */classWhiteSnowmanimplementsISnowman{protected$head;protected$body;publicfunction__construct(){$this->head=newWhiteHead();$this->body=newWhiteBody();}publicfunctiondrawHead($x,$y){$this->head->drawHead($x,$y);}publicfunctiondrawBody($x,$y){$this->body->drawBody($x,$y);}}/** * Class RedSnowman - concrete factory */classRedSnowmanimplementsISnowman{protected$head;protected$body;publicfunction__construct(){$this->head=newRedHead();$this->body=newRedBody();}publicfunctiondrawHead($x,$y){$this->head->drawHead($x,$y);}publicfunctiondrawBody($x,$y){$this->body->drawBody($x,$y);}}functionsnowman(ISnowman$snowman){$snowman->drawHead(1,1);$snowman->drawBody(1,2);}$typeSnowman='red';// мы выбираем тип семейства в начале кодаif($typeSnowman=='red')$snowman=newRedSnowman();else$snowman=newWhiteSnowman();snowman($snowman);
fromabcimportABCMeta,abstractmethodclassBeer(metaclass=ABCMeta):passclassSnack(metaclass=ABCMeta):@abstractmethoddefinteract(self,beer:Beer)->None:passclassAbstractShop(metaclass=ABCMeta):@abstractmethoddefbuy_beer(self)->Beer:pass@abstractmethoddefbuy_snack(self)->Snack:passclassTuborg(Beer):passclassStaropramen(Beer):passclassPeanuts(Snack):definteract(self,beer:Beer)->None:print('Мы выпили по бутылке пива {} и закусили его арахисом'.format(beer.__class__.__name__))classChips(Snack):definteract(self,beer:Beer)->None:print('Мы выпили несколько банок пива {} и съели пачку чипсов'.format(beer.__class__.__name__))classExpensiveShop(AbstractShop):defbuy_beer(self)->Beer:returnTuborg()defbuy_snack(self)->Snack:returnPeanuts()classCheapShop(AbstractShop):defbuy_beer(self)->Beer:returnStaropramen()defbuy_snack(self)->Snack:returnChips()if__name__=='__main__':expensive_shop=ExpensiveShop()cheap_shop=CheapShop()print('OUTPUT:')beer=expensive_shop.buy_beer()snack=cheap_shop.buy_snack()snack.interact(beer)beer=cheap_shop.buy_beer()snack=expensive_shop.buy_snack()snack.interact(beer)'''OUTPUT:Мы выпили несколько банок пива Tuborg и съели пачку чипсовМы выпили по бутылке пива Staropramen и закусили его арахисом'''
abstractclassAbstractTerrestrialAnimal{defwalk:String}abstractclassAbstractWaterAnimal{defswim:String}abstractclassAbstractZoo{defgetCity:StringdefgetTerrestrialAnimal:AbstractTerrestrialAnimaldefgetWaterAnimal:AbstractWaterAnimal}classWolverineextendsAbstractTerrestrialAnimal{overridedefwalk:String="Wolverine is walking"}classHoneyBadgerextendsAbstractTerrestrialAnimal{overridedefwalk:String="Honey badger is walking"}classWalrusextendsAbstractWaterAnimal{overridedefswim:String="Walrus is swimming"}classSeaLionextendsAbstractWaterAnimal{overridedefswim:String="Sea lion is swimming"}classMunichZooextendsAbstractZoo{overridedefgetCity:String="Munich"overridedefgetTerrestrialAnimal:AbstractTerrestrialAnimal=newWolverineoverridedefgetWaterAnimal:AbstractWaterAnimal=newWalrus}classCapeTownZooextendsAbstractZoo{overridedefgetCity:String="CapeTown"overridedefgetTerrestrialAnimal:AbstractTerrestrialAnimal=newHoneyBadgeroverridedefgetWaterAnimal:AbstractWaterAnimal=newSeaLion}objectAbstractFactoryTest{privatedeftestZoo(zoo:AbstractZoo):Unit={println(s"Zoo of ${zoo.getCity}:")println(zoo.getTerrestrialAnimal.walk)println(zoo.getWaterAnimal.swim)}defmain(args:Array[String])Unit={testZoo(newCapeTownZoo)testZoo(newMunichZoo)}}
packagemainimport"fmt"typeUnitinterface{What()string}typeActioninterface{What()string}typePlaceinterface{What()string}typeTransportFactoryinterface{MakeUnit()UnitMakeAction()ActionMakePlace()Place}typeCarstruct{}func(selfCar)What()string{return"car"}typeRidestruct{}func(selfRide)What()string{return"ride"}typeRoadstruct{}func(selfRoad)What()string{return"road"}typeLandTransportFactorystruct{}func(selfLandTransportFactory)MakeUnit()Unit{return&Car{}}func(selfLandTransportFactory)MakeAction()Action{return&Ride{}}func(selfLandTransportFactory)MakePlace()Place{return&Road{}}typeBoatstruct{}func(selfBoat)What()string{return"boat"}typeSailstruct{}func(selfSail)What()string{return"sail"}typeSeastruct{}func(selfSea)What()string{return"sea"}typeSeaTransportFactorystruct{}func(selfSeaTransportFactory)MakeUnit()Unit{return&Boat{}}func(selfSeaTransportFactory)MakeAction()Action{return&Sail{}}func(selfSeaTransportFactory)MakePlace()Place{return&Sea{}}funcaction(factoryTransportFactory){unit:=factory.MakeUnit()unit_action:=factory.MakeAction()place:=factory.MakePlace()fmt.Printf("The %s %ss over the %s.\n",unit.What(),unit_action.What(),place.What())}funcmain(){action(&LandTransportFactory{})action(&SeaTransportFactory{})}
Вывод
The car rides over the road.
The boat sails over the sea.
moduleAbstractFactoryPattern# Provide an interface for creating families of related or dependent objects without specifying their concrete classes# Abstract FactoryclassWarriorFactorydefcreate_knightraiseNotImplementedErrorenddefcreate_archerraiseNotImplementedErrorendend# Concrete FactoryclassOrcWarriorFactory<WarriorFactorydefcreate_knightOrcKnight.newenddefcreate_archerOrcArcher.newendend# Concrete FactoryclassElfWarriorFactory<WarriorFactorydefcreate_knightElfKnight.newenddefcreate_archerElfArcher.newendend# Abstract ProductclassKnightdefinspectself.class.name.split('::').lastendend# Abstract ProductclassArcherdefinspectself.class.name.split('::').lastendend# ProductclassOrcKnight<Knightend# ProductclassElfKnight<Knightend# ProductclassOrcArcher<Archerend# ProductclassElfArcher<Archerend# ClientclassArmydefinitialize(factory)@knights=[]3.times{@knights<<factory.create_knight}@archers=[]3.times{@archers<<factory.create_archer}enddefinspect"Knights #{@knights.map(&:inspect)} Archers #{@archers.map(&:inspect)}"endenddefself.runorcs=Army.new(OrcWarriorFactory.new)puts"Orcs army: #{orcs.inspect}"elves=Army.new(ElfWarriorFactory.new)puts"Elves army: #{elves.inspect}"endendAbstractFactoryPattern.run# Orcs army: Knights ["OrcKnight", "OrcKnight", "OrcKnight"] Archers ["OrcArcher", "OrcArcher", "OrcArcher"]# Elves army: Knights ["ElfKnight", "ElfKnight", "ElfKnight"] Archers ["ElfArcher", "ElfArcher", "ElfArcher"]
Литература
Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидес. Приёмы объектно-ориентированного проектирования. Паттерны проектирования = Design Patterns: Elements of Reusable Object-Oriented Software. — СПб.: «Питер», 2007. — С. 366. — ISBN 978-5-469-01136-1. (также ISBN 5-272-00355-1)