Главная
Статьи





07.11.2022


07.11.2022


07.11.2022


06.11.2022


06.11.2022






Абстрактная фабрика (шаблон проектирования)

23.01.2022

Абстрактная фабрика (англ. Abstract factory) — порождающий шаблон проектирования, предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретных классов. Шаблон реализуется созданием абстрактного класса Factory, который представляет собой интерфейс для создания компонентов системы (например, для оконного интерфейса он может создавать окна и кнопки). Затем пишутся классы, реализующие этот интерфейс.

Назначение

Предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретных классов.

Реализация

Плюсы

  • изолирует конкретные классы;
  • упрощает замену семейств продуктов;
  • гарантирует сочетаемость продуктов.

Минусы

  • сложно добавить поддержку нового вида продуктов.

Применение

  • Система не должна зависеть от того, как создаются, компонуются и представляются входящие в неё объекты.
  • Входящие в семейство взаимосвязанные объекты должны использоваться вместе и вам необходимо обеспечить выполнение этого ограничения.
  • Система должна конфигурироваться одним из семейств составляющих её объектов.
  • Требуется предоставить библиотеку объектов, раскрывая только их интерфейсы, но не реализацию.

Примеры

Пример на Swift

Исходный текст на языке 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#

Исходный код на языке C Sharp using System; namespace DoFactory.GangOfFour.Abstract.Structural { class MainApp { /// <summary> /// Точка входа в приложение /// </summary> public static void Main() { // Вызов абстрактной фабрики № 1 AbstractFactory factory1 = new ConcreteFactory1(); Client client1 = new Client(factory1); client1.Run(); // Вызов абстрактной фабрики № 2 AbstractFactory factory2 = new ConcreteFactory2(); Client client2 = new Client(factory2); client2.Run(); // Ожидание ввода Console.ReadKey(); } } /// <summary> /// Класс абстрактной фабрики /// </summary> abstract class AbstractFactory { public abstract AbstractProductA CreateProductA(); public abstract AbstractProductB CreateProductB(); } /// <summary> /// Класс фабрики № 1 /// </summary> class ConcreteFactory1 : AbstractFactory { public override AbstractProductA CreateProductA() { return new ProductA1(); } public override AbstractProductB CreateProductB() { return new ProductB1(); } } /// <summary> /// Класс фабрики № 2 /// </summary> class ConcreteFactory2 : AbstractFactory { public override AbstractProductA CreateProductA() { return new ProductA2(); } public override AbstractProductB CreateProductB() { return new ProductB2(); } } /// <summary> /// Абстрактный класс продукта А /// </summary> abstract class AbstractProductA { } /// <summary> /// Абстрактный класс продукта В /// </summary> abstract class AbstractProductB { public abstract void Interact(AbstractProductA a); } /// <summary> /// Первый класс продукта типа А /// </summary> class ProductA1 : AbstractProductA { } /// <summary> /// Первый класс продукта типа В /// </summary> class ProductB1 : AbstractProductB { public override void Interact(AbstractProductA a) { Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name); } } /// <summary> /// Второй класс продукта типа А /// </summary> class ProductA2 : AbstractProductA { } /// <summary> /// Второй класс продукта типа В /// </summary> class ProductB2 : AbstractProductB { public override void Interact(AbstractProductA a) { Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name); } } /// <summary> /// Класс клиента, в котором происходит взаимодействие между объектами /// </summary> 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

Исходный текст на языке 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

Исходный текст на языке 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

Исходный текст на языке 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

Исходный текст на языке 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

Исходный текст на языке 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. ", 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

Исходный текст на языке 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"]