Абстрактная фабрика (Abstract Factory) — различия между версиями

Материал из Вики ИТ мехмата ЮФУ
Перейти к: навигация, поиск
(Пример)
(Код)
 
(не показано 12 промежуточных версий этого же участника)
Строка 2: Строка 2:
 
__NOTOC__
 
__NOTOC__
 
=== Назначение ===
 
=== Назначение ===
 +
Предоставляет интерфейс для создания компонентов системы.
 +
===Другое название===
 +
Инструментарий (Kit)
  
 
=== Описание ===
 
=== Описание ===
 +
В проекте с многими объектами может возникнуть необходимость менять поведение этих объектов в совокупности. Например, при переносе библиотеки графических компонентов на другую операционную систему полностью меняется реализация этих компонентов.
 +
 +
В этом случае можно создать абстрактный класс AbstractFactory, который будет содержать методы создания компонентов каждого вида, а в подклассах переопределить эти методы, вызывая создание конкретных компонентов (в нашем примере каждый подкласс будет ответственен за создание компонентов, связанных с одной операционной системой).
 +
 +
Это позволяет не менять клиентский код приложения, работающего с компонентами и обеспечивает переносимость.
 +
 +
===Использование===
 +
Паттерн Абстрактная фабрика используется когда:
 +
* Система должна конфигурироваться одним из семейств составляющих ее объектов
 +
* Необходимо создать набор объектов, открывая только их интерфейсы
  
 
=== Реализация ===
 
=== Реализация ===
 
==== Диаграмма классов ====
 
==== Диаграмма классов ====
[[Изображение:.png|.png]]
+
[[Изображение:AbstractCommon.png]]
  
 
==== Участники====
 
==== Участники====
*
+
*'''AbstractFactory''' - абстрактная фабрика
 
+
Определяет интерфейс для операций, создающих абстрактные продукты
==== Диаграмма последовательности ====
+
*'''ConcreteFactory''' - конкретная фабрика
[[Изображение:.png]]
+
Реализует операции, создавая конкретные продукты
 +
*'''AbstractProduct''' - абстрактный продукт
 +
Определяет интерфейс для типа продукта
 +
*'''ConcreteProduct''' - конкретный продукт
 +
Определяет продукт, создаваемый конкретной фабрикой.
 +
*'''Client''' - клиент
 +
Использует интерфейсы AbstractFactory и AbstractProduct
  
 
=== Код===
 
=== Код===
Строка 67: Строка 86:
 
             r2.SetSide(Direction.West, d);
 
             r2.SetSide(Direction.West, d);
  
        return aMaze;
+
    return aMaze;
 
         }
 
         }
 
     }
 
     }
Строка 73: Строка 92:
 
     public class BombedWall: Wall
 
     public class BombedWall: Wall
 
     {
 
     {
        public override object Clone()
 
        {
 
            return new BombedWall();
 
        }
 
 
     }
 
     }
  
Строка 83: Строка 98:
 
         public RoomWithABomb(int n): base(n)
 
         public RoomWithABomb(int n): base(n)
 
         { }
 
         { }
        public override object Clone()
 
        {
 
            return new RoomWithABomb(this.RoomNumber);
 
        }
 
 
     }
 
     }
  
 
     public class BombedMazeFactory : MazeFactory
 
     public class BombedMazeFactory : MazeFactory
 
     {
 
     {
    public override Room MakeRoom(int n)
+
     
{  
+
        public override Room MakeRoom(int n)
 +
{  
 
             return new RoomWithABomb(n);  
 
             return new RoomWithABomb(n);  
 
         }
 
         }
 
         public override Wall MakeWall()
 
         public override Wall MakeWall()
    {  
+
{  
 
             return new BombedWall();  
 
             return new BombedWall();  
 
         }
 
         }
Строка 116: Строка 128:
  
 
=== Достоинства и недостатки ===
 
=== Достоинства и недостатки ===
*  
+
*Изолирует клиента от деталей реализации классов
 +
*Упрощает замену семейства продуктов
 +
*Недостаток: поддержка нового вида продукта трудна
  
 
=== Варианты ===
 
=== Варианты ===
*
+
*Вместо создания разных семейств продуктов в подклассах абстрактной фабрики - в самой фабрике во все методы передавать идентификатор семейства создаваемых продуктов

Текущая версия на 12:51, 31 августа 2014

К основной странице курса

Назначение

Предоставляет интерфейс для создания компонентов системы.

Другое название

Инструментарий (Kit)

Описание

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

В этом случае можно создать абстрактный класс AbstractFactory, который будет содержать методы создания компонентов каждого вида, а в подклассах переопределить эти методы, вызывая создание конкретных компонентов (в нашем примере каждый подкласс будет ответственен за создание компонентов, связанных с одной операционной системой).

Это позволяет не менять клиентский код приложения, работающего с компонентами и обеспечивает переносимость.

Использование

Паттерн Абстрактная фабрика используется когда:

  • Система должна конфигурироваться одним из семейств составляющих ее объектов
  • Необходимо создать набор объектов, открывая только их интерфейсы

Реализация

Диаграмма классов

AbstractCommon.png

Участники

  • 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);
        }
    }
}

Достоинства и недостатки

  • Изолирует клиента от деталей реализации классов
  • Упрощает замену семейства продуктов
  • Недостаток: поддержка нового вида продукта трудна

Варианты

  • Вместо создания разных семейств продуктов в подклассах абстрактной фабрики - в самой фабрике во все методы передавать идентификатор семейства создаваемых продуктов