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

 


Связанные темы