Билеты ООП / 21. пАттерн Builder
.docxЦель:
Отделяет конструирование сложного объекта от его представления, так что в результате одного и того же процесса конструирования могут получаться разные представления.
Плюсы:
-
позволяет изменять внутреннее представление продукта;
-
изолирует код, реализующий конструирование и представление;
-
дает более тонкий контроль над процессом конструирования.
Применение:
-
алгоритм создания сложного объекта не должен зависеть от того, из каких частей состоит объект и как они стыкуются между собой;
-
процесс конструирования должен обеспечивать различные представления конструируемого объекта.
Рассмотрим участников шаблона:
Builder — это, собственно, и есть Строитель, представляющий собой абстрактный интерфейс для создания объекта Product по частям;
ConcreteBuilder — конкретный интерфейс Строителя. Если вы решите, что ваш Строитель собирает ПК, то конкретные строители могут создавать компьютеры разных марок, например Apple, Acer или Hewlett-Packard;
Director — класс, занимающийся конструированием объекта, используя интерфейс, представленный Строителем;
Product — итоговый продукт, получающийся в результате конструирования.
Пример: будем собирать объект HappyMeal. В первом случае вы соберете бюджетный вариант HappyMeal (маленькая порция пепси-колы, гамбургер, картошка и игрушка), а во втором — BigHappyMeal (гамбургер вы замените на бигмак и увеличите порцию напитка).
Продукт:
class HappyMeal
{
// содержит информацию о // составе HappyMeal
ArrayList parts = new ArrayList();
// Добавляете информацию // о новой составной части
public void Add(string part)
{
parts.Add(part);
}
// Выводите информацию о // всем наборе
public void Show()
{
Console.WriteLine(" Happy Meal Parts ——-");
foreach (string part in parts)
Console.WriteLine (part);
}
}
Все данные о составе HappyMeal будут храниться в массиве ArrayList. С помощью метода Add добавьте данные в ArrayList. Метод Show просто «проходит» по вашему объекту, выводя строку за строкой.
Строитель:
// "Строитель — абстрактный интерфейс для создания объекта HappyMeal по частям"
abstract class HappyMealBuilder
{
public abstract void BuildBurger();
public abstract void BuildPepsi();
public abstract void BuildFries();
public abstract void BuildToy();
public abstract HappyMeal GetProduct();
}
Конкретный Строитель 1, создающий большой HappyMeal:
// Строитель для большого // HappyMeal
class BigHappyMealBuilder : HappyMealBuilder
{
private HappyMeal happy_meal = new HappyMeal();
public override void BuildBurger()
{
happy_meal.Add("BigMac");
}
public override void BuildPepsi()
{
happy_meal.Add("Pepsi 0.7");
}
public override void BuildFries()
{
happy_meal.Add("BigFries");
}
public override void BuildToy()
{
happy_meal.Add("Two toys");
}
public override HappyMeal GetProduct()
{
return happy_meal;
}
}
Вы видите, что у данного класса есть одна переменная happy_meal, имеющая тип вашего продукта. Ее-то вы и будете использовать во всех переопределенных методах. В каждом из них вы должны добавить информацию о продукте с помощью метода Add, описанного ранее. В методе GetProduct вы просто возвращаете вашу переменную.
С маленьким HappyMeal все делается аналогично:
// Строитель для маленького // HappyMeal
class SmallHappyMealBuilder : HappyMealBuilder
{
private HappyMeal happy_meal = new HappyMeal();
public override void BuildBurger()
{
happy_meal.Add("Hamburger");
}
public override void BuildPepsi()
{
happy_meal.Add("Pepsi 0.3");
}
public override void BuildFries()
{
happy_meal.Add("SmallFries");
}
public override void BuildToy()
{
happy_meal.Add("One toy");
}
public override HappyMeal GetProduct()
{
return happy_meal;
}
}
Пришло время реализовать класс Director, который будет отвечать за конструирование объектов:
// "Этот класс будет // заниматься конструированием"
class Director
{
// Конструирование объекта // по частям
public void Construct(HappyMealBuilder builder)
{
builder.BuildBurger();
builder.BuildPepsi();
builder.BuildFries();
builder.BuildToy();
}
}
Как видно из фрагмента листинга, все действие сосредоточено вокруг метода Construct. В него вы передаете объект HappyMealBuilder, после чего начинаете пошаговую сборку, поочередно вызывая каждый из Build-методов.
Наконец поработайте с созданными вами классами:
public static void Main()
{
// Создаете класс // Director и строителей // для двух наборов // HappyMeal
Director director = new Director();
HappyMealBuilder big_hmbuilder = new BigHappyMealBuilder();
HappyMealBuilder small_hmbuilder = new SmallHappyMealBuilder();
// Конструируете два // продукта
director.Construct(big_hmbuilder);
HappyMeal hm1 = big_hmbuilder.GetProduct();
hm1.Show();
director.Construct(small_hmbuilder);
HappyMeal hm2 = small_hmbuilder.GetProduct();
hm2.Show();
// Ожидаете действия // пользователя
Console.Read();
}
Работа с созданными классами очень проста. Сначала вы создаете объект класса Director, а затем два объекта Builder, которые будут переданы в метод Construct класса Director, чтобы собрать объект HappyMeal. После конструирования очередного HappyMeal вы передаете его в переменную hm1 или hm2 типа HappyMeal и вызываете метод Show, показывающий содержимое набора.