Абстрактная фабрика (Abstract Factory) — различия между версиями
Admin (обсуждение | вклад) (→Диаграмма классов) |
Admin (обсуждение | вклад) (→Код) |
||
(не показано 5 промежуточных версий этого же участника) | |||
Строка 7: | Строка 7: | ||
=== Описание === | === Описание === | ||
+ | В проекте с многими объектами может возникнуть необходимость менять поведение этих объектов в совокупности. Например, при переносе библиотеки графических компонентов на другую операционную систему полностью меняется реализация этих компонентов. | ||
+ | |||
+ | В этом случае можно создать абстрактный класс AbstractFactory, который будет содержать методы создания компонентов каждого вида, а в подклассах переопределить эти методы, вызывая создание конкретных компонентов (в нашем примере каждый подкласс будет ответственен за создание компонентов, связанных с одной операционной системой). | ||
+ | |||
+ | Это позволяет не менять клиентский код приложения, работающего с компонентами и обеспечивает переносимость. | ||
+ | |||
===Использование=== | ===Использование=== | ||
+ | Паттерн Абстрактная фабрика используется когда: | ||
+ | * Система должна конфигурироваться одним из семейств составляющих ее объектов | ||
+ | * Необходимо создать набор объектов, открывая только их интерфейсы | ||
=== Реализация === | === Реализация === | ||
==== Диаграмма классов ==== | ==== Диаграмма классов ==== | ||
− | [[Изображение:AbstractCommon | + | [[Изображение:AbstractCommon.png]] |
==== Участники==== | ==== Участники==== | ||
Строка 83: | Строка 92: | ||
public class BombedWall: Wall | public class BombedWall: Wall | ||
{ | { | ||
− | |||
− | |||
− | |||
− | |||
} | } | ||
Строка 93: | Строка 98: | ||
public RoomWithABomb(int n): base(n) | public RoomWithABomb(int n): base(n) | ||
{ } | { } | ||
− | |||
− | |||
− | |||
− | |||
} | } | ||
Строка 127: | Строка 128: | ||
=== Достоинства и недостатки === | === Достоинства и недостатки === | ||
− | * | + | *Изолирует клиента от деталей реализации классов |
+ | *Упрощает замену семейства продуктов | ||
+ | *Недостаток: поддержка нового вида продукта трудна | ||
=== Варианты === | === Варианты === | ||
− | * | + | *Вместо создания разных семейств продуктов в подклассах абстрактной фабрики - в самой фабрике во все методы передавать идентификатор семейства создаваемых продуктов |
Текущая версия на 12:51, 31 августа 2014
Назначение
Предоставляет интерфейс для создания компонентов системы.
Другое название
Инструментарий (Kit)
Описание
В проекте с многими объектами может возникнуть необходимость менять поведение этих объектов в совокупности. Например, при переносе библиотеки графических компонентов на другую операционную систему полностью меняется реализация этих компонентов.
В этом случае можно создать абстрактный класс AbstractFactory, который будет содержать методы создания компонентов каждого вида, а в подклассах переопределить эти методы, вызывая создание конкретных компонентов (в нашем примере каждый подкласс будет ответственен за создание компонентов, связанных с одной операционной системой).
Это позволяет не менять клиентский код приложения, работающего с компонентами и обеспечивает переносимость.
Использование
Паттерн Абстрактная фабрика используется когда:
- Система должна конфигурироваться одним из семейств составляющих ее объектов
- Необходимо создать набор объектов, открывая только их интерфейсы
Реализация
Диаграмма классов
Участники
- AbstractFactory - абстрактная фабрика
Определяет интерфейс для операций, создающих абстрактные продукты
- ConcreteFactory - конкретная фабрика
Реализует операции, создавая конкретные продукты
- AbstractProduct - абстрактный продукт
Определяет интерфейс для типа продукта
- ConcreteProduct - конкретный продукт
Определяет продукт, создаваемый конкретной фабрикой.
- Client - клиент
Использует интерфейсы AbstractFactory и AbstractProduct
Код
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MazeCommon;
namespace MazeGameAbstractFactory
{
public class MazeFactory
{
public virtual Maze MakeMaze()
{
return new Maze();
}
public virtual Wall MakeWall()
{
return new Wall();
}
public virtual Room MakeRoom(int n)
{
return new Room(n);
}
public virtual Door MakeDoor(Room r1, Room r2)
{
return new Door(r1,r2);
}
};
public class MazeGame
{
public Maze CreateMaze(MazeFactory f)
{
Maze aMaze = f.MakeMaze();
Room r1 = f.MakeRoom(1);
Room r2 = f.MakeRoom(2);
Door d = f.MakeDoor(r1,r2);
aMaze.AddRoom(r1);
aMaze.AddRoom(r2);
r1.SetSide(Direction.North, f.MakeWall());
r1.SetSide(Direction.East, d);
r1.SetSide(Direction.South, f.MakeWall());
r1.SetSide(Direction.West, f.MakeWall());
r2.SetSide(Direction.North, f.MakeWall());
r2.SetSide(Direction.East, f.MakeWall());
r2.SetSide(Direction.South, f.MakeWall());
r2.SetSide(Direction.West, d);
return aMaze;
}
}
public class BombedWall: Wall
{
}
public class RoomWithABomb: Room
{
public RoomWithABomb(int n): base(n)
{ }
}
public class BombedMazeFactory : MazeFactory
{
public override Room MakeRoom(int n)
{
return new RoomWithABomb(n);
}
public override Wall MakeWall()
{
return new BombedWall();
}
};
public class ProgramAbstractFactory
{
static void Main(string[] args)
{
Console.WriteLine("AbstractFactory");
MazeGame game = new MazeGame();
BombedMazeFactory f = new BombedMazeFactory();
game.CreateMaze(f);
}
}
}
Достоинства и недостатки
- Изолирует клиента от деталей реализации классов
- Упрощает замену семейства продуктов
- Недостаток: поддержка нового вида продукта трудна
Варианты
- Вместо создания разных семейств продуктов в подклассах абстрактной фабрики - в самой фабрике во все методы передавать идентификатор семейства создаваемых продуктов