Абстрактная фабрика (шаблон проектирования)
Из Википедии, бесплатной энциклопедии
Абстрактная фабрика | |
---|---|
Abstract factory | |
Тип | порождающий |
Назначение | Предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретных классов. |
Структура | |
Применяется в случаях |
|
Плюсы |
|
Минусы |
|
Описан в Design Patterns | Да |
Абстрактная фабрика (англ. Abstract factory) — порождающий шаблон проектирования, предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретных классов. Шаблон реализуется созданием абстрактного класса Factory, который представляет собой интерфейс для создания компонентов системы (например, для оконного интерфейса он может создавать окна и кнопки). Затем пишутся классы, реализующие этот интерфейс[2].
Назначение[править | править код]
Предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретных классов.
Реализация[править | править код]
Плюсы[править | править код]
- изолирует конкретные классы;
- упрощает замену семейств продуктов;
- гарантирует сочетаемость продуктов.
Минусы[править | править код]
- сложно добавить поддержку нового вида продуктов.
Применение[править | править код]
- Система не должна зависеть от того, как создаются, компонуются и представляются входящие в неё объекты.
- Входящие в семейство взаимосвязанные объекты должны использоваться вместе и вам необходимо обеспечить выполнение этого ограничения.
- Система должна конфигурироваться одним из семейств составляющих её объектов.
- Требуется предоставить библиотеку объектов, раскрывая только их интерфейсы, но не реализацию.
Примеры[править | править код]
Пример на Kotlin[править | править код]
import kotlin.random.Random // next interfaces are products of abstract factories interface Executor interface Legislator interface Judge // just wrapper for government data class Governor( val name: String, val executor: Executor, val legislator: Legislator, val judge: Judge ) { fun work() { 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 interface interface GovernmentFactory { fun createExecutor(): Executor fun createJudge(): Judge fun createLegislator(): Legislator /** * Template Method Pattern */ fun createGovernment(name: String): Governor { return Governor( name, createExecutor(), createLegislator(), createJudge() ) } } data class Monarch( val name: String ) : Judge, Executor, Legislator // implementation of abstract factory object RussianMonarchyFactory : GovernmentFactory { private val ivanGrozny = Monarch("Иван Грозный") override fun createExecutor(): Executor { return ivanGrozny } override fun createJudge(): Judge { return ivanGrozny } override fun createLegislator(): Legislator { return ivanGrozny } } data class PresidentCandidate( val name: String, private val myJudgeGuy: Judge ) : Executor { fun setJudge(): Judge { return myJudgeGuy } } private val CONGRESS_MEMBER_COUNT = 535 data class Congress( val republicans: Int, val democrats: Int = CONGRESS_MEMBER_COUNT - republicans ) : Legislator class AmericanElectorate( private val presidentCandidates: List<PresidentCandidate> ) { fun choosePresident(): PresidentCandidate { return presidentCandidates.random()// here should be logic of choosing the president } fun chooseParliament(): Legislator { val delta = Random.nextInt(15) return Congress(CONGRESS_MEMBER_COUNT / 2 - delta) } } // implementation of abstract factory class PresidentRepublicFactory( private val electorate: AmericanElectorate, private var currentPresident: PresidentCandidate ) : GovernmentFactory { override fun createExecutor(): Executor { currentPresident = electorate.choosePresident() return currentPresident } override fun createJudge(): Judge { return currentPresident.setJudge() } override fun createLegislator(): Legislator { return electorate.chooseParliament() } } data class ElectivePerson( val name: String ): Judge, Executor data class Parliament( val description: String, // left, centrist or right parties val president: ElectivePerson, val judge: Judge ): Legislator class EuropeanElectorate( val people: List<ElectivePerson> ) { fun chooseParliament(): Parliament { return Parliament( listOf("left", "centrist", "right").random(), people.random(), people.random() ) } } // implementation of abstract factory class ParliamentRepublicFactory( private val electorate: EuropeanElectorate, private var electedParliament: Parliament ): GovernmentFactory { override fun createExecutor(): Executor { return electedParliament.president } override fun createJudge(): Judge { return electedParliament.judge } override fun createLegislator(): Legislator { electedParliament = electorate.chooseParliament() return electedParliament } /** * should be overridden because we should select parliament firstly */ override fun createGovernment(name: String): Governor { val parliament = createLegislator() return Governor(name, createExecutor(), parliament, createJudge()) } } fun main() { val biden = PresidentCandidate("Biden", ElectivePerson("Kamalla Harris")) val americanElectorate = AmericanElectorate(listOf( biden, PresidentCandidate("Trump", ElectivePerson("Obama")) )) val europeanElectorate = 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 countries mapOf( "Rus" to RussianMonarchyFactory, "USA" to PresidentRepublicFactory(americanElectorate, biden), "Deutschland" to ParliamentRepublicFactory(europeanElectorate, Parliament("Communists", ElectivePerson("Climate Liar"), ElectivePerson("War Criminal"), )) ).map { (country, govFactory) -> govFactory.createGovernment(country) // create governments }.forEach { it.work() // enforce them to work } }
Пример на Swift[править | править код]
//: Playground - noun: a place where people can play /// <summary> /// Класс абстрактной фабрики /// </summary> protocol AbstractFactory { func createProductA() -> AbstractProductA func createProductB() -> AbstractProductB } /// <summary> /// Класс фабрики № 1 /// </summary> class ConcreteFactory1: AbstractFactory { public func createProductA() -> AbstractProductA { return ProductA1() } public func createProductB() -> AbstractProductB { return ProductB1() } } /// <summary> /// Класс фабрики № 2 /// </summary> class ConcreteFactory2 : AbstractFactory { public func createProductA() -> AbstractProductA { return ProductA2() } public func createProductB() -> AbstractProductB { return ProductB2() } } /// <summary> /// Абстрактный класс продукта А /// </summary> protocol AbstractProductA {} // /// <summary> /// Абстрактный класс продукта В /// </summary> protocol AbstractProductB { func interact(a: AbstractProductA) } /// <summary> /// Первый класс продукта типа А /// </summary> class ProductA1 : AbstractProductA {} /// <summary> /// Первый класс продукта типа В /// </summary> class ProductB1 : AbstractProductB { public func interact(a: AbstractProductA) { print("\(type(of:self)) interacts with \(type(of: a.self))") } } /// <summary> /// Второй класс продукта типа А /// </summary> class ProductA2 : AbstractProductA {} /// <summary> /// Второй класс продукта типа В /// </summary> class ProductB2 : AbstractProductB { public func interact(a: AbstractProductA) { print("\(type(of:self)) interacts with \(type(of: a.self))") } } /// <summary> /// Класс клиента, в котором происходит взаимодействие между объектами /// </summary> class Client { private let _abstractProductA: AbstractProductA private let _abstractProductB: AbstractProductB // Конструктор public init(factory: AbstractFactory) { _abstractProductB = factory.createProductB(); _abstractProductA = factory.createProductA(); } public func run() { _abstractProductB.interact(a: _abstractProductA) } } /// <summary> /// Точка входа в приложение /// </summary> // Вызов абстрактной фабрики № 1 let factory1 = ConcreteFactory1() let client1 = Client(factory: factory1) client1.run() // Вызов абстрактной фабрики № 2 let factory2 = ConcreteFactory2() let client2 = Client(factory: factory2) client2.run()
Пример на C#[3][править | править код]
using System; namespace DoFactory.GangOfFour.Abstract.Structural { class MainApp { public static void Main() { AbstractFactory factory1 = new ConcreteFactory1(); Client client1 = new Client(factory1); client1.Run(); AbstractFactory factory2 = new ConcreteFactory2(); Client client2 = new Client(factory2); client2.Run(); Console.ReadKey(); } } abstract class AbstractFactory { public abstract AbstractProductA CreateProductA(); public abstract AbstractProductB CreateProductB(); } class ConcreteFactory1 : AbstractFactory { public override AbstractProductA CreateProductA() { return new ProductA1(); } public override AbstractProductB CreateProductB() { return new ProductB1(); } } class ConcreteFactory2 : AbstractFactory { public override AbstractProductA CreateProductA() { return new ProductA2(); } public override AbstractProductB CreateProductB() { return new ProductB2(); } } abstract class AbstractProductA { } abstract class AbstractProductB { public abstract void Interact(AbstractProductA a); } class ProductA1 : AbstractProductA { } class ProductB1 : AbstractProductB { public override void Interact(AbstractProductA a) { Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name); } } class ProductA2 : AbstractProductA { } class ProductB2 : AbstractProductB { public override void Interact(AbstractProductA a) { Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name); } } class Client { private AbstractProductA _abstractProductA; private AbstractProductB _abstractProductB; public Client(AbstractFactory factory) { _abstractProductB = factory.CreateProductB(); _abstractProductA = factory.CreateProductA(); } public void Run() { _abstractProductB.Interact(_abstractProductA); } } }
Пример на Java[править | править код]
public class AbstractFactoryExample { public static void main(String[] args) { AbstractFactory factory1 = new ConcreteFactory1(); Client client1 = new Client(factory1); client1.execute(); AbstractFactory factory2 = new ConcreteFactory2(); Client client2 = new Client(factory2); client2.execute(); } } class Client { private AbstractProductA productA; private AbstractProductB productB; Client(AbstractFactory factory) { productA = factory.createProductA(); productB = factory.createProductB(); } void execute() { productB.interact(productA); } } interface AbstractFactory { AbstractProductA createProductA(); AbstractProductB createProductB(); } interface AbstractProductA { void interact(AbstractProductB b); } interface AbstractProductB { void interact(AbstractProductA a); } class ConcreteFactory1 implements AbstractFactory { @Override public AbstractProductA createProductA() { return new ProductA1(); } @Override public AbstractProductB createProductB() { return new ProductB1(); } } class ConcreteFactory2 implements AbstractFactory { @Override public AbstractProductA createProductA() { return new ProductA2(); } @Override public AbstractProductB createProductB() { return new ProductB2(); } } class ProductA1 implements AbstractProductA { @Override public void interact(AbstractProductB b) { System.out.println(this.getClass().getName() + " interacts with " + b.getClass().getName()); } } class ProductB1 implements AbstractProductB { @Override public void interact(AbstractProductA a) { System.out.println(this.getClass().getName() + " interacts with " + a.getClass().getName()); } } class ProductA2 implements AbstractProductA { @Override public void interact(AbstractProductB b) { System.out.println(this.getClass().getName() + " interacts with " + b.getClass().getName()); } } class ProductB2 implements AbstractProductB { @Override public void interact(AbstractProductA a) { System.out.println(this.getClass().getName() + " interacts with " + a.getClass().getName()); } }
Пример на PHP5[править | править код]
interface IHead { public function drawHead($x, $y); } class RedHead implements IHead { public function drawHead($x, $y) { echo 'Your red head in axis x = ' . $x . ' and axis y = ' . $y . '</ br>' . PHP_EOL; } } class WhiteHead implements IHead { public function drawHead($x, $y) { echo 'Your white head in axis x = ' . $x . ' and axis y = ' . $y . '</ br>' . PHP_EOL; } } interface IBody { public function drawBody($x, $y); } class RedBody implements IBody { public function drawBody($x, $y) { echo 'Your red body in axis x = ' . $x . ' and axis y = ' . $y . '</ br>' . PHP_EOL; } } class WhiteBody implements IBody { public function drawBody($x, $y) { echo 'Your white body in axis x = ' . $x . ' and axis y = ' . $y . '</ br>' . PHP_EOL; } } /** * Interface ISnowman - this is abstract factory */ interface ISnowman { public function drawHead($x, $y); public function drawBody($x, $y); } /** * Class WhiteSnowman - concrete factory */ class WhiteSnowman implements ISnowman { protected $head; protected $body; 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); } } /** * Class RedSnowman - concrete factory */ class RedSnowman implements ISnowman { protected $head; protected $body; 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); $snowman->drawBody(1,2); } $typeSnowman = 'red'; // мы выбираем тип семейства в начале кода if($typeSnowman == 'red') $snowman = new RedSnowman(); else $snowman = new WhiteSnowman(); snowman($snowman);
Пример на Python[править | править код]
from abc import ABCMeta, abstractmethod class Beer(metaclass=ABCMeta): pass class Snack(metaclass=ABCMeta): @abstractmethod def interact(self, beer: Beer) -> None: pass class AbstractShop(metaclass=ABCMeta): @abstractmethod def buy_beer(self) -> Beer: pass @abstractmethod def buy_snack(self) -> Snack: pass class Tuborg(Beer): pass class Staropramen(Beer): pass class Peanuts(Snack): def interact(self, beer: Beer) -> None: print('Мы выпили по бутылке пива {} и закусили его арахисом'.format( beer.__class__.__name__)) class Chips(Snack): def interact(self, beer: Beer) -> None: print('Мы выпили несколько банок пива {} и съели пачку чипсов'.format( beer.__class__.__name__)) class ExpensiveShop(AbstractShop): def buy_beer(self) -> Beer: return Tuborg() def buy_snack(self) -> Snack: return Peanuts() class CheapShop(AbstractShop): def buy_beer(self) -> Beer: return Staropramen() def buy_snack(self) -> Snack: return Chips() 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 и закусили его арахисом '''
Пример на Scala[править | править код]
abstract class AbstractTerrestrialAnimal { def walk: String } abstract class AbstractWaterAnimal { def swim: String } abstract class AbstractZoo { def getCity: String def getTerrestrialAnimal: AbstractTerrestrialAnimal def getWaterAnimal: AbstractWaterAnimal } class Wolverine extends AbstractTerrestrialAnimal { override def walk: String = "Wolverine is walking" } class HoneyBadger extends AbstractTerrestrialAnimal { override def walk: String = "Honey badger is walking" } class Walrus extends AbstractWaterAnimal { override def swim: String = "Walrus is swimming" } class SeaLion extends AbstractWaterAnimal { override def swim: String = "Sea lion is swimming" } class MunichZoo extends AbstractZoo { override def getCity: String = "Munich" override def getTerrestrialAnimal: AbstractTerrestrialAnimal = new Wolverine override def getWaterAnimal: AbstractWaterAnimal = new Walrus } class CapeTownZoo extends AbstractZoo { override def getCity: String = "CapeTown" override def getTerrestrialAnimal: AbstractTerrestrialAnimal = new HoneyBadger override def getWaterAnimal: AbstractWaterAnimal = new SeaLion } object AbstractFactoryTest { private def testZoo(zoo: AbstractZoo): Unit = { 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) } }
Пример на Go[править | править код]
package main import "fmt" type Unit interface { What() string } type Action interface { What() string } type Place interface { What() string } type TransportFactory interface { MakeUnit() Unit MakeAction() Action MakePlace() Place } type Car struct{} func (self Car) What() string { return "car" } type Ride struct{} func (self Ride) What() string { return "ride" } type Road struct{} func (self Road) What() string { return "road" } type LandTransportFactory struct{} func (self LandTransportFactory) MakeUnit() Unit { return &Car{} } func (self LandTransportFactory) MakeAction() Action { return &Ride{} } func (self LandTransportFactory) MakePlace() Place { return &Road{} } type Boat struct{} func (self Boat) What() string { return "boat" } type Sail struct{} func (self Sail) What() string { return "sail" } type Sea struct{} func (self Sea) What() string { return "sea" } type SeaTransportFactory struct{} func (self SeaTransportFactory) MakeUnit() Unit { return &Boat{} } func (self SeaTransportFactory) MakeAction() Action { return &Sail{} } func (self SeaTransportFactory) MakePlace() Place { return &Sea{} } func action(factory TransportFactory) { 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()) } func main() { action(&LandTransportFactory{}) action(&SeaTransportFactory{}) }
Вывод
The car rides over the road. The boat sails over the sea.
Пример на Ruby[править | править код]
module AbstractFactoryPattern # Provide an interface for creating families of related or dependent objects without specifying their concrete classes # Abstract Factory class WarriorFactory def create_knight raise NotImplementedError end def create_archer raise NotImplementedError end end # Concrete Factory class OrcWarriorFactory < WarriorFactory def create_knight OrcKnight.new end def create_archer OrcArcher.new end end # Concrete Factory class ElfWarriorFactory < WarriorFactory def create_knight ElfKnight.new end def create_archer ElfArcher.new end end # Abstract Product class Knight def inspect self.class.name.split('::').last end end # Abstract Product class Archer def inspect self.class.name.split('::').last end end # Product class OrcKnight < Knight end # Product class ElfKnight < Knight end # Product class OrcArcher < Archer end # Product class ElfArcher < Archer end # Client class Army def initialize(factory) @knights = [] 3.times { @knights << factory.create_knight } @archers = [] 3.times { @archers << factory.create_archer } end def inspect "Knights #{@knights.map(&:inspect)} Archers #{@archers.map(&:inspect)}" end end def self.run orcs = Army.new(OrcWarriorFactory.new) puts "Orcs army: #{orcs.inspect}" elves = Army.new(ElfWarriorFactory.new) puts "Elves army: #{elves.inspect}" end end AbstractFactoryPattern.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)
Ссылки[править | править код]
- Паттерн Abstract Factory (абстрактная фабрика) — назначение, описание, реализация на C++, достоинства и недостатки
Примечания[править | править код]
- ↑ Паттерн Abstract Factory . Дата обращения: 14 июня 2013. Архивировано 14 июня 2013 года.
- ↑ Порождающие шаблоны: Абстрактная фабрика (Abstract factory) . Дата обращения: 14 июня 2013. Архивировано 14 июня 2013 года.
- ↑ Abstract Factory .NET Design Pattern in C# and VB - dofactory.com . www.dofactory.com. Дата обращения: 3 марта 2016. Архивировано 3 марта 2016 года.