Абстрактная фабрика (шаблон проектирования)
Абстрактная фабрика (англ. Abstract factory) — порождающий шаблон проектирования, предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретных классов. Шаблон реализуется созданием абстрактного класса Factory, который представляет собой интерфейс для создания компонентов системы (например, для оконного интерфейса он может создавать окна и кнопки). Затем пишутся классы, реализующие этот интерфейс[2].
Абстрактная фабрика | |
---|---|
Abstract factory | |
Тип | порождающий |
Назначение | Предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретных классов. |
Структура | |
Применяется в случаях |
|
Плюсы |
|
Минусы |
|
Описан в Design Patterns | Да |
Назначение
Предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретных классов.
Реализация
Плюсы
- изолирует конкретные классы;
- упрощает замену семейств продуктов;
- гарантирует сочетаемость продуктов.
Минусы
- сложно добавить поддержку нового вида продуктов.
Применение
- Система не должна зависеть от того, как создаются, компонуются и представляются входящие в неё объекты.
- Входящие в семейство взаимосвязанные объекты должны использоваться вместе и вам необходимо обеспечить выполнение этого ограничения.
- Система должна конфигурироваться одним из семейств составляющих её объектов.
- Требуется предоставить библиотеку объектов, раскрывая только их интерфейсы, но не реализацию.
Примеры
Пример на 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#[3]
Исходный код на языке 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.\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
Исходный текст на языке 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 (абстрактная фабрика) — назначение, описание, реализация на С++, достоинства и недостатки
Примечания
- Паттерн 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.
This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.