Patterns. Паттерни. Реалізація паттерну Builder на C#

Реалізація паттерну Builder на C#

Перед вивченням даної теми рекомендується ознайомитись з наступною темою:


Зміст


Пошук на інших ресурсах:




1. Структура паттерну Builder

У найбільш загальному випадку структура паттерну Builder зображена на рисунку 1.

Структура паттерну Builder

Рисунок 1. Структура паттерну Builder

 

2. Реалізація паттерну Builder на C#. Приклад
2.1. Структурна схема рішення задачі

У прикладі демонструється реалізація паттерну Builder на мові C#, структура якого зображена на рисунку 2.

Паттерн Builder. Побудова продукту з 3-х частин

Рисунок 2. Паттерн Builder. Побудова продукту з 3-х частин

Оголошуються наступні класи:

  • Product – клас, що є продуктом (результатом роботи паттерну). Це є довільний клас. У демонстраційних цілях в цьому класі оголошується три цілочисельних змінних, кожна з яких умовно вважається частиною продукту;
  • Builder – абстрактний клас, що служить інтерфейсом між розпорядником (Director) та класом, що створює конкретний об’єкт (ConcreteBuilder);
  • ConcreteBuilder – клас, що будує конкретний об’єкт;
  • Director – клас, що є розпорядником. Цей клас будує (конфігурує) об’єкт класу ConcreteBuilder для використання його клієнтом;
  • Program – клас, що є клієнтом. У цьому класі реалізується функція main(), в якій продемонстровано роботу клієнта. Клієнт звертається до розпорядника (Director) для того, щоб той побудував об’єкт класу ConcreteBuilder. Потім побудований об’єкт повертається клієнту в методі GetResult().

 

2.2. Програма на мові C#

Текст програми на мові C# наступний

using System;

namespace ConsoleApp8
{
  // Паттерн Builder. Приклад реалізації на C#
  // 1. Клас, що є продуктом, містить три частини
  class Product
  {
    // Деякі внутрішні змінні
    private int part1, part2, part3;

    // Конструктор
    public Product()
    {
      part1 = 0;
      part2 = 0;
      part3 = 0;
    }

    // Методи доступу
    public int GetPart1() { return part1; }
    public int GetPart2() { return part2; }
    public int GetPart3() { return part3; }

    public void SetPart1(int part1)
    {
      this.part1 = part1;
    }

    public void SetPart2(int part2)
    {
      this.part2 = part2;
    }

    public void SetPart3(int part3)
    {
      this.part3 = part3;
    }
  }

  // 2. Клас, що є інтерфейсом між розпорядником та конкретним будівником
  abstract class Builder
  {
    // Метод, що створює продукт
    public abstract void CreateProduct();

    // Методи, що будують частини продукта
    public abstract void BuildPart1(int part);
    public abstract void BuildPart2(int part);
    public abstract void BuildPart3(int part);

    // Метод, що повертає продукт клієнту
    public abstract Product GetProduct();
  }

  // Клас - конкретний будівник, успадковує абстрактний клас Builder
  class ConcreteBuilder : Builder
  {
    // Внутрішня змінна - посилання на продукт
    private Product currentBuilder;

    // Методи, що оголошуються в абстрактному класі Builder, їх потрібно реалізувати
    public override void CreateProduct()
    {
      currentBuilder = new Product();
    }

    public override void BuildPart1(int part)
    {
      currentBuilder.SetPart1(part);
    }

    public override void BuildPart2(int part)
    {
      currentBuilder.SetPart2(part);
    }

    public override void BuildPart3(int part)
    {
      currentBuilder.SetPart3(part);
    }

    public override Product GetProduct()
    {
      return currentBuilder;
    }
  }

  // Клас-розпорядник, містить методи побудови об'єкту Product з частин
  class Director
  {
    // Посилання на Builder
    private Builder builder;

    // Конструктор - ініціалізується екземпляром Builder
    public Director(Builder _builder)
    {
      builder = _builder;
    }

    // Метод, що будує об'єкт класу Product з частин
    public void Construct()
    {
      // Побудувати екземпляр класу Product
      builder.CreateProduct();
      builder.BuildPart1(10);
      builder.BuildPart2(20);
      builder.BuildPart3(30);
    }
  }

  // Клас, що містить функцію клієнта
  class Program
  {
    static void Main(string[] args)
    {
      // Це є клієнт
      // 1. Оголосити посилання на продукт
      Product product;

      // 2. Створити конкретного будівника
      Builder B = new ConcreteBuilder();

      // 3. Створити розпорядника та зконфігурувати його будівником
      Director D = new Director(B);

      // 4. Викликати методи побудови продукту - довірити це розпоряднику
      D.Construct();

      // 5. Повернути побудований продукт клієнту
      product = B.GetProduct();

      // 6. Перевірити, як побудований продукт
      Console.WriteLine("product.part1 = {0}", product.GetPart1());
      Console.WriteLine("product.part2 = {0}", product.GetPart2());
      Console.WriteLine("product.part3 = {0}", product.GetPart3());
    }
  }
}

 

2.3. Результат роботи програми
product.part1 = 10
product.part2 = 20
product.part3 = 30

 

3. Приклад використання паттерну Builder для генерування масивів випадкових чисел
3.1. Умова задачі

Використовуючи засоби мови C# та можливості паттерну Builder розробити програму для генерування об’єктів, що є масивами випадкових чисел. Масиви випадкових чисел представлені наступними класами:

  • ArrayRandomInt – масив з цілих чисел. Для даного масиву вказується діапазон;
  • ArrayRandomChar – масив випадкових символів від ‘A’ до ‘Z’.

 

3.2. Рисунок, що відображає структурну схему розв’язку задачі

На рисунку 3 зображено структуру паттерну Builder, яка відображає розв’язок даної задачі.

Паттерн Builder. Генерування об’єктів - масивів випадкових чисел

Рисунок 3. Паттерн Builder. Генерування об’єктів – масивів випадкових чисел

Як видно з рисунку, клас-розпорядник може використовувати два класи-будівники BuildRandomInt та BuildRandomChar.

 

3.3. Розв’язок. Програма на мові C#. Додаток типу Console Application

Текст програми, що розв’язує задачу, наступний.

using System;

namespace ConsoleApp9
{
  // 1.   Класи, що є продуктами
  // 1.1. ArrayRandomInt - масив випадкових цілих чисел
  class ArrayRandomInt
  {
    // Оголосити внутрішню змінну - екземпляр масиву
    private int[] A;

    // Конструктор класу з трьома параметрами
    public ArrayRandomInt(int count, int min, int max)
    {
      // Створити екземпляр класу Random
      Random rndNum = new Random();

      // Побудувати масив випадкових чисел
      A = new int[count];
      for (int i = 0; i < count; i++)
      {
        A[i] = rndNum.Next(min, max + 1);
      }
    }

    // Метод, що повертає масив
    public int[] GetArrayInt()
    {
      return A;
    }
  }

  // 1.2. Масив символів від 'A' до 'Z'
  class ArrayRandomChar
  {
    // Масив випадкових символів від 'A' до 'Z'
    private char[] A;

    public ArrayRandomChar(int count)
    {
      // Створити екземпляр класу Random
      Random rndChar = new Random();

      // Побудувати масив A
      A = new char[count];
      int t;

      for (int i = 0; i < count; i++)
      {
        // Отримати випадковий символ від 'A' до 'Z'
        A[i] = (char)(rndChar.Next((int)('Z' - 'A' + 1)) + (int)'A');
      }
    }

    // Метод, що повертає масив
    public char[] GetArrayChar()
    {
      return A;
    }
  }

  // 2. Клас, що є інтерфейсом з клієнтом для генерування об'єкту типу int
  class Builder
  {
    // У класі оголошуються методи, що надаються класу-розпоряднику
    virtual public void BuildArrayInt(int count, int min, int max) { }
    virtual public void BuildArrayChar(int count) { }

    // Методи, що повертають конкретні об'єкти клієнту
    virtual public ArrayRandomInt GetResultInt()
    {
      return null;
    }

    virtual public ArrayRandomChar GetResultChar()
    {
      return null;
    }
  }

  // 3. Класи - будівники екземплярів ArrayRandomInt та ArrayRandomChar
  class BuildRandomInt : Builder
  {
    private ArrayRandomInt A;

    override public void BuildArrayInt(int count, int min, int max)
    {
      // Побудувати екземпляр класу ArrayRandomInt
      A = new ArrayRandomInt(count, min, max);
    }

    override public ArrayRandomInt GetResultInt()
    {
      return A;
    }
  }

  class BuildRandomChar : Builder
  {
    private ArrayRandomChar A;

    public override void BuildArrayChar(int count)
    {
      A = new ArrayRandomChar(count);
    }

    public override ArrayRandomChar GetResultChar()
    {
      return A;
    }
  }

  // 4. Клас, що виступає розпорядником
  class Director
  {
    private Builder builder;

    // Конструктор класу
    public Director(Builder _builder)
    {
      builder = _builder;
    }

    // Метод, що будує масив випадкових цілих чисел
    public void ConstructInt()
    {
      // Побудувати масив з 10 цілих чисел в діапазоні від 5 до 15
      builder.BuildArrayInt(10, 5, 15);
    }

    public void ConstructChar()
    {
      // Побудувати масив з 15 символів типу char
      builder.BuildArrayChar(15);
    }
  }

  // Клас, що виступає клієнтом
  class Program
  {
    static void Main(string[] args)
    {
      // Це є клієнт
      // 1. Генерування об'єкту класу ArrayRandomInt
      // 1.1. Оголосити продукт
      ArrayRandomInt AI; // Це є результат - об'єкт-масив цілих чисел

      // 1.2. Оголосити клас-будівник
      Builder BI = new BuildRandomInt();

      // 1.3. Оголосити розпорядника та зконфігурувати його конкретним будівником
      Director D = new Director(BI);
      D.ConstructInt(); // Побудувати об'єкт-масив цілих чисел

      // 1.4. Передати масив клієнту
      AI = BI.GetResultInt();

      // 1.5. Перевірити результат
      int[] arrInt = AI.GetArrayInt();
      Console.WriteLine("Array AI:");
      for (int i = 0; i < arrInt.Length; i++)
        Console.Write("{0}   ", arrInt[i]);
      Console.WriteLine();

      // -----------------------------------------
      // 2. Генерування об'єкту класу ArrayRandomChar
      // 2.1. Оголосити продукт
      ArrayRandomChar AC;

      // 2.2. Оголосити клас-будівник
      BuildRandomChar BC = new BuildRandomChar();

      // 2.3. Оголосити клас розпорядник і сформувати його будівником
      Director DC = new Director(BC);

      // 2.4. Збудувати масив значень типу char
      DC.ConstructChar();

      // 2.5. Передати масив клієнту
      AC = BC.GetResultChar();

      // 2.6. Вивести отриманий масив для перевірки
      char[] arrChar = AC.GetArrayChar();
      Console.WriteLine("Array AC:");
      for (int i = 0; i < arrChar.Length; i++)
        Console.Write("{0} ", arrChar[i]);
      Console.WriteLine();
    }
  }
}

 

3.4. Пояснення до програми

Як видно з рисунку 3, у програмі використовуються два класи-будівники BuildRandomInt та BuildRandomChar, які містять два методи побудови об’єктів класів:

  • метод BuildArrayInt() – створює екземпляр класу ArrayRandomInt;
  • метод BuildArrayChar() –   створює екземпляр класу ArrayRandomChar.

Класи ArrayRandomInt та ArrayRandomChar є продуктами, які передаються клієнту.

Клас Director є класом-розпорядником. У цьому класі реалізовано два методи ConstructInt() та ConstructChar(), з яких викликаються методи BuildArrayInt() та BuildArrayChar() з конкретними параметрами (довжина масиву, діапазон значень).

Клас Builder служить інтерфейсом між класом-розпорядником Director та класами-будівниками BuildRandomInt та BuildRandomChar.

Можливий був й інший варіант реалізації задачі, в якому клас Builder був розбитий на два підкласи, наприклад BuilderInt та BuilderChar.

 

3.5. Результат виконання програми

Після запуску на виконання програма видасть наступний результат

Array AI:
5 10 14 7 5   11 10 8 9 14
Array AC:
J M G N M S C H N L S Y E L V

 


Зв’язані теми