Абстрактная фабрика

Абстрактная фабрика

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

Содержание

Цель

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

Плюсы

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

Минусы

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

Применимость

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

Пример Java

	public abstract class FinancialToolsFactory {
		public abstract TaxProcessor createTaxProcessor();
		public abstract ShipFeeProcessor createShipFeeProcessor();
	}
 
	public abstract class ShipFeeProcessor {
		abstract void calculateShipFee(Order order);
	}
 
	public abstract class TaxProcessor {
		abstract void calculateTaxes(Order order);
	}
 
        // Factories
	public class CanadaFinancialToolsFactory extends FinancialToolsFactory {
		public TaxProcessor createTaxProcessor() {
			return new CanadaTaxProcessor();
		}
		public ShipFeeProcessor createShipFeeProcessor() {
			return new CanadaShipFeeProcessor();
		}
	}
 
	public class EuropeFinancialToolsFactory extends FinancialToolsFactory {
		public TaxProcessor createTaxProcessor() {
			return new EuropeTaxProcessor();
		}
		public ShipFeeProcessor createShipFeeProcessor() {
			return new EuropeShipFeeProcessor();
		}
	}
 
	// Products
	public class EuropeShipFeeProcessor extends ShipFeeProcessor {
		public void calculateShipFee(Order order) {
		// insert here Europe specific ship fee calculation
		}
	}	
 
	public class CanadaShipFeeProcessor extends ShipFeeProcessor {
		public void calculateShipFee(Order order) {
		// insert here Canada specific ship fee calculation
		}
	}
 
	public class EuropeTaxProcessor extends TaxProcessor {
		public void calculateTaxes(Order order) {
			// insert here Europe specific taxt calculation
		}
	}
 
	public class CanadaTaxProcessor extends TaxProcessor {
		public void calculateTaxes(Order order) {
			// insert here Canada specific taxt calculation
		}
	}
 
	// Client
	public class OrderProcessor {
		private TaxProcessor taxProcessor;
		private ShipFeeProcessor shipFeeProcessor;
 
		public OrderProcessor(FinancialToolsFactory factory) {
			taxProcessor = factory.createTaxProcessor();
			shipFeeProcessor = factory.createShipFeeProcessor();	
		}
		public void processOrder (Order order)	{
			// ....
			taxProcessor.calculateTaxes(order);
			shipFeeProcessor.calculateShipFee(order);
			// ....
		}
	}
 
	// Integration with the overall application
	enum CountryCode {
        	EU,
	        CA
    	}
 
	public class Application {
		public static void main(final String... args) {
			// .....
			final CountryCode countryCode = CountryCode.EU;
 
			final FinancialToolsFactory factory;
			switch (countryCode) {
            			case EU:
					factory = new EuropeFinancialToolsFactory();
	                		break;
                		case CA:
					factory = new CanadaFinancialToolsFactory();
                    			break;
                		default:
                    			throw new IllegalStateException();
			}
 
			final OrderProcessor orderProcessor = new OrderProcessor(factory);
			orderProcessor.processOrder(new Order());
		}
	}

Пример С++

#include <iostream>
 
// AbstractProductA
class ICar
	{
	public:
		virtual void info() = 0;
	};
 
// ConcreteProductA1
class Ford : public ICar
	{
	public:
		virtual void info() 
			{ 
			std::cout << "Ford" << std::endl; 
			}
	};
 
//ConcreteProductA2
class Toyota : public ICar
	{
	public:
		virtual void info() 
			{ 
			std::cout << "Toyota" << std::endl; 
			}
	};
 
// AbstractProductB
class IEngine
	{
	public:
		virtual void getPower() = 0;
	};
 
// ConcreteProductB1
class FordEngine : public IEngine
	{
	public:
		virtual void getPower() 
			{ 
			std::cout << "Ford Engine 4.4" << std::endl; 
			}
	};
 
//ConcreteProductB2
class ToyotaEngine : public IEngine
	{
	public:
		virtual void getPower() 
			{ 
			std::cout << "Toyota Engine 3.2" << std::endl; 
			}
	};
 
 
// AbstractFactory
class CarFactory
	{
	public:
		ICar* getNewCar()
			{
			return createCar();
			}
 
		IEngine* getNewEngine()
			{
			return createEngine();
			}
 
	protected:
		virtual ICar*		createCar()		= 0;
		virtual IEngine*	createEngine()	= 0;
	};
 
// ConcreteFactory1
class FordFactory : public CarFactory
	{
	protected:
		// from CarFactory
		virtual ICar* createCar()
			{
			return new Ford();
			}
 
		virtual IEngine* createEngine()
			{
			return new FordEngine();
			}
	};
 
// ConcreteFactory2
class ToyotaFactory : public CarFactory
	{
	protected:
		// from CarFactory
		virtual ICar* createCar()
			{
			return new Toyota();
			}
		virtual IEngine* createEngine()
			{
			return new ToyotaEngine();
			}
	};
 
 
int main()
	{
 
	CarFactory* curFactory	= NULL;
	ICar*		myCar		= NULL;
	IEngine*	myEngine	= NULL;
 
	ToyotaFactory	toyotaFactory;
	FordFactory		fordFactory;
 
	curFactory = &toyotaFactory;
 
	myCar = curFactory->getNewCar();
	myCar->info();
	myEngine = curFactory->getNewEngine();
	myEngine->getPower();
	delete myCar;
	delete myEngine;
 
 
	curFactory = &fordFactory;
	myCar = curFactory->getNewCar();
 	myCar->info();
	myEngine = curFactory->getNewEngine();
	myEngine->getPower();
	delete myCar;
	delete myEngine;
 
	return 0;
	}

Пример С#

  class MainApp
  {
    public static void Main()
    {
      // Abstract factory #1
      AbstractFactory factory1 = new ConcreteFactory1();
      Client c1 = new Client(factory1);
      c1.Run();
 
      // Abstract factory #2
      AbstractFactory factory2 = new ConcreteFactory2();
      Client c2 = new Client(factory2);
      c2.Run();
 
      // Wait for user input
      Console.Read();
    }
  }
 
  // "AbstractFactory"
 
  abstract class AbstractFactory
  {
    public abstract AbstractProductA CreateProductA();
    public abstract AbstractProductB CreateProductB();
  }
 
  // "ConcreteFactory1"
 
  class ConcreteFactory1 : AbstractFactory
  {
    public override AbstractProductA CreateProductA()
    {
      return new ProductA1();
    }
    public override AbstractProductB CreateProductB()
    {
      return new ProductB1();
    }
  }
 
  // "ConcreteFactory2"
 
  class ConcreteFactory2 : AbstractFactory
  {
    public override AbstractProductA CreateProductA()
    {
      return new ProductA2();
    }
    public override AbstractProductB CreateProductB()
    {
      return new ProductB2();
    }
  }
 
  // "AbstractProductA"
 
  abstract class AbstractProductA
  {
  }
 
  // "AbstractProductB"
 
  abstract class AbstractProductB
  {
    public abstract void Interact(AbstractProductA a);
  }
 
  // "ProductA1"
 
  class ProductA1 : AbstractProductA
  {
  }
 
  // "ProductB1"
 
  class ProductB1 : AbstractProductB
  {
    public override void Interact(AbstractProductA a)
    {
      Console.WriteLine(this.GetType().Name +
        " interacts with " + a.GetType().Name);
    }
  }
 
  // "ProductA2"
 
  class ProductA2 : AbstractProductA
  {
  }
 
  // "ProductB2"
 
  class ProductB2 : AbstractProductB
  {
    public override void Interact(AbstractProductA a)
    {
      Console.WriteLine(this.GetType().Name +
        " interacts with " + a.GetType().Name);
    }
  }
 
  // "Client" - the interaction environment of the products
 
  class Client
  {
    private AbstractProductA AbstractProductA;
    private AbstractProductB AbstractProductB;
 
    // Constructor
    public Client(AbstractFactory factory)
    {
      AbstractProductB = factory.CreateProductB();
      AbstractProductA = factory.CreateProductA();
    }
 
    public void Run()
    {
      AbstractProductB.Interact(AbstractProductA);
    }
  }

Пример
// AbstractProducts
// создаем абстрактные классы продуктов
 
	// AbstractProductA
	// "интерфейс" пошлины за перевозку
	function ShipFeeProcessor() {
		this.calculate = function(order) { };
	}
 
	// AbstractProductB
	// "интерфейс" налога
	function TaxProcessor() {
		this.calculate = function(order) { };
	}
 
 
// Products
// создаем реализацию абстрактных классов
 
	// Product A1
	// класс для расчета пошлины за перевозку для Европы
	function EuropeShipFeeProcessor() {
		this.calculate = function(order) {
			// перегрузка метода calculate ShipFeeProcessor
			return 11 + order;
		};
	}
	EuropeShipFeeProcessor.prototype = new ShipFeeProcessor();
	EuropeShipFeeProcessor.prototype.constructor = EuropeShipFeeProcessor;
 
	// Product A2
	// класс для расчета пошлины за перевозку для Канады
	function CanadaShipFeeProcessor() {
		this.calculate = function(order) {
			// перегрузка метода calculate ShipFeeProcessor
			return 12 + order;
		};
	}
	CanadaShipFeeProcessor.prototype = new ShipFeeProcessor();
	CanadaShipFeeProcessor.prototype.constructor = CanadaShipFeeProcessor;
 
	// Product B1
	// класс для расчета налогов для Европы
	function EuropeTaxProcessor() {
		this.calculate = function(order) {
			// перегрузка метода calculate TaxProcessor
			return 21 + order;
		};
	}
	EuropeTaxProcessor.prototype = new TaxProcessor();
	EuropeTaxProcessor.prototype.constructor = EuropeTaxProcessor;
 
	// Product B2
	// класс для расчета налогов для Канады
	function CanadaTaxProcessor() {
		this.calculate = function(order) {
			// перегрузка метода calculate TaxProcessor
			return 22 + order;
		};
	}
	CanadaTaxProcessor.prototype = new TaxProcessor();
	CanadaTaxProcessor.prototype.constructor = CanadaTaxProcessor;
 
 
// AbstractFactory
// "интерфейс" фабрики
	function FinancialToolsFactory() {
		this.createShipFeeProcessor = function() {};
		this.createTaxProcessor = function() {};
	};
 
 
// Factories
 
	// ConcreteFactory1
	// Европейская фабрика будет возвращать нам экземпляры классов...
	function EuropeFinancialToolsFactory() {
		this.createShipFeeProcessor = function() {
			// ...для расчета пошлины за перевозку для Европы
			return new EuropeShipFeeProcessor();
		};
		this.createTaxProcessor = function() {
			// ...для расчета налогов для Европы
			return new EuropeTaxProcessor();
		};
	};
	EuropeFinancialToolsFactory.prototype = new FinancialToolsFactory();
	EuropeFinancialToolsFactory.prototype.constructor = EuropeFinancialToolsFactory;
 
	// ConcreteFactory2
	// аналогично, Канадская фабрика будет возвращать нам экземпляры классов...
	function CanadaFinancialToolsFactory() {
		this.createShipFeeProcessor = function() {
			// ...для расчета пошлины за перевозку для Канады
			return new CanadaShipFeeProcessor();
		};
		this.createTaxProcessor = function() {
			// ...для расчета налогов для Канады
			return new CanadaTaxProcessor();
		};
	};
	CanadaFinancialToolsFactory.prototype = new FinancialToolsFactory();
	CanadaFinancialToolsFactory.prototype.constructor = CanadaFinancialToolsFactory;
 
 
// Client
// класс для заказа товара
	function OrderProcessor() {
		var taxProcessor;
		var shipFeeProcessor;
 
		this.orderProcessor = function(factory) {
			// метод создает экзепляры классов для:
			shipFeeProcessor = factory.createShipFeeProcessor(); // расчета пошлин за перевозку
			taxProcessor = factory.createTaxProcessor(); // расчета налогов
		};
 
		this.processOrder = function(order)	{
			// когда экземпляры классов для расчета созданы, нам надо только воспользоваться ими
			// ...
			var resShipFee = shipFeeProcessor.calculate(order);
			var resTax = taxProcessor.calculate(order);
			// ...
		};
 
		this.debug = function(str, order) {
			// для наглядности
			alert(str +": "+ shipFeeProcessor.calculate(order) +", "+ taxProcessor.calculate(order));
		};
	}
 
 
// использование
 
var eu = new OrderProcessor(); // создаем "пустой" класс для заказа товара
eu.orderProcessor(new EuropeFinancialToolsFactory()); // передаем ему новый экзепляр нужной нам фабрики
eu.processOrder(100); // производим заказ
eu.debug("eu", 100); // тест выведет: "eu: 111, 121"
 
var ca = new OrderProcessor();
ca.orderProcessor(new CanadaFinancialToolsFactory());
ca.processOrder(0);
ca.debug("ca", 0); // тест выведет: "ca: 12, 22"

Object Pascal

program AbstractFactory;
 
{$APPTYPE CONSOLE}
 
uses  SysUtils;
 
type
  // AbstractProduct
  ICar = Class
  public
   function info: String; virtual; abstract;
  end;
 
// ConcreteProductA
  Ford = Class(ICar)
  public
   function info: String; override;
  end;
 
// ConcreteProductB
   Toyota  = Class(ICar)
  public
   function info: String; override;
  end;
 
// AbstractFactory
  CarFactory = Class
  public
   function CreateCar:ICar; virtual; abstract;
  end;
 
 
// ConcreteFactoryA
  FordFactory = Class(CarFactory)
  private
   function CreateCar:ICar; override;
  end;
 
// ConcreteFactoryB
  ToyotaFactory = Class(CarFactory)
  private
   function CreateCar:ICar; override;
  end;
 
{ Ford }
function Ford.info: String;
begin
 Result:='Ford';
end;
 
{ Toyota }
function Toyota.info: String;
begin
 Result:='Toyota';
end;
 
{ FordFactory }
function FordFactory.CreateCar: ICar;
begin
  Result:=Ford.Create;
end;
 
{ ToyotaFactory }
function ToyotaFactory.CreateCar: ICar;
begin
  Result:=Toyota.Create;
end;  
 
var CF: CarFactory;
    C: ICar;
    i: Char;
begin
 writeln('Abstract factory');
 writeln('ToyotaFactory');
 Cf:= ToyotaFactory.Create;
 C:=CF.CreateCar;
 writeln(C.info);
 C.Free;
 Readln(i);
 
 writeln('FordFactory');
 Cf:= FordFactory.Create;
 C:=CF.CreateCar;
 writeln(C.info);
 C.Free;
 Readln(i);
end.

См. также

Литература


порождающие шаблоны проектирования
[править]
абстрактная фабрика | строитель | фабричный метод | прототип | одиночка | отложенная инициализация

Wikimedia Foundation. 2010.

Игры ⚽ Поможем сделать НИР

Полезное


Смотреть что такое "Абстрактная фабрика" в других словарях:

  • Абстрактная фабрика (шаблон проектирования) — Шаблон проектирования Абстрактная фабрика Abstract factory Тип: порождающий Описан в Design Patterns Да Абстрактная фабрика (англ. Abstract factory) порождающий шаблон проектирования, позволяющий изменять поведение системы …   Википедия

  • Фабрика (шаблон проектирования) — Фабричный метод (англ. Factory Method) порождающий шаблон проектирования, предоставляющий подклассам интерфейс для создания экземпляров некоторого класса. В момент создания наследники могут определить, какой класс инстанциировать. Иными словами,… …   Википедия

  • Марбургская обойная фабрика — Тип акционерное общество с ограниченной ответственностью и компания коммандитное товарищество Год основания 1845 …   Википедия

  • Design Patterns — Приёмы объектно ориентированного проектирования. Паттерны проектирования. Design Patterns: Elements of Reusable Object Oriented Software Автор: «Банда четырёх»: Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссидс …   Википедия

  • Команда (шаблон проектирования) — У этого термина существуют и другие значения, см. Команда. Шаблон проектирования Команда Command Тип: поведенческий Назначение: для обработки команды в виде объекта …   Википедия

  • Порождающие шаблоны проектирования — Порождающие шаблоны (англ. Creational patterns)  шаблоны проектирования, которые абстрагируют процесс инстанцирования. Они позволяют сделать систему независимой от способа создания, композиции и представления объектов. Шаблон,… …   Википедия

  • Шаблон проектирования — У этого термина существуют и другие значения, см. Паттерн. В разработке программного обеспечения, шаблон проектирования или паттерн (англ. design pattern) повторимая архитектурная конструкция, представляющая собой решение проблемы… …   Википедия

  • Одиночка (шаблон проектирования) — У этого термина существуют и другие значения, см. Одиночка. Шаблон проектирования Одиночка Singleton Тип: порождающий Описан в Design Patterns Да Одиночка (англ. Singleton) в программировании  …   Википедия

  • Интерфейс (шаблон проектирования) — Шаблон проектирования Интерфейс Interface Описан в Design Patterns Нет В информатике, шаблон интерфейса не является особым шаблоном среди шаблонов проектирования. Он является общим методом для структурирования компьютерных программ для того …   Википедия

  • Фабричный метод (шаблон проектирования) — Шаблон проектирования Фабричный метод Factory Method Тип: порождающий Описан в Design Patterns Да Фабричный метод (англ. Factory Method)  порождающий шаблон проектирования, предоставляющий подклассам интерфейс для созда …   Википедия


Поделиться ссылкой на выделенное

Прямая ссылка:
Нажмите правой клавишей мыши и выберите «Копировать ссылку»