Patterns. Паттерн Singleton (Одиночка). Особенности реализации на C#

Паттерн Singleton (Одиночка). Особенности реализации на C#

Данная тема есть продолжением темы:


Содержание


Поиск на других ресурсах:




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

Структура паттерна Singleton изображена на рисунке 1.

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

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

 

2. Структура паттерна Singleton с привязкой к коду C#. Рисунок с объяснением

 

Структура паттерна Singleton. Пример на C#

Рисунок 2. Структура паттерна Singleton. Пример на C#

Экземпляр (объект) класса Singleton получается путем вызова метода Instance(). В методе Instance() происходит создание экземпляра благодаря вызову конструктора класса с помощью оператора new.

Поскольку, конструктор класса Singleton реализован с модификатором доступа protected, то создать экземпляр этого класса из методов других классов не удастся. Однако, расширить возможности данного класса можно.

Если в задаче допускается возможность расширения класса-одиночки унаследованными подклассами, то конструктор объявляется как protected. Если нужно запретить расширение класса-одиночки, то конструктор должен быть объявлен как private.

 

3. Текст программы на C#, реализующей паттерн Singleton

 

using System;
using static System.Console;

namespace ConsoleApp9
{
  // Реализация паттерна Singleton - Одиночка
  class Singleton
  {
    // Статический метод, который возвращает экземпляр класса Singleton.
    // Данный метод может быть заменен соответствующим свойством.
    public static Singleton Instance()
    {
      if (_instance == null)
      {
        _instance = new Singleton();
        return _instance;
      }
      else
      {
        return null;
      }
    }

    // Конструктор класса, объявленный как protected, для того чтобы:
    // - запретить создание экземпляра класса оператором new;
    // - можно было наследовать данный класс.
    protected Singleton()
    {
    }

    // Статическая внутренняя переменная, которая хранит экземпляр класса.
    // К этой переменной есть доступ из методов данного класса.
    // Из методов других классов доступа к переменной нет.
    private static Singleton _instance = null;

    // -------------------------------------------------
    // Другие внутренние поля класса
    private int d;

    // Свойство для доступа к полю d
    public int D
    {
      get { return d; }
      set { d = value; }
    }

    // Метод, который выводит значение поля d
    public void Print(string text)
    {
      WriteLine("------------------");
      WriteLine("{0}. d = {1}", text, d);
    }
  }

  // Класс, выступающий клиентом
  class Program
  {
    static void Main(string[] args)
    {
      // Это есть код клиента.
      // Создать единственный экземпляр класса Singleton
      Singleton obj1 = Singleton.Instance();

      // Проверить obj1 на равенство null
      if (obj1 != null)
      {
        obj1.D = 25;
        obj1.Print("obj1");
      }
      else
        WriteLine("obj1 == null");

      // Попытка создать другой экземпляр класса
      Singleton obj2 = Singleton.Instance();

      if (obj2 != null)
      {
        obj2.D = 77;
        obj2.Print("obj2");
      }
      else
        WriteLine("obj2 == null");
    }
  }
}

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

------------------
obj1. d = 25
obj2 == null

 

4. Использование статического свойства вместо метода

Язык C# допускает использование свойств вместо методов. Поэтому, по желанию, в вышеприведенном коде метод Instance() может быть заменен на свойство. Ниже приведен пример объявления такого свойства

 

// Статическое свойство, которое возвращает экземпляр класса Singleton
public static Singleton Instance
{
  get
  {
    if (_instance == null)
    {
      _instance = new Singleton();
      return _instance;
    }
    else
      return null;
  }
}

Использование свойства в методе клиента может быть, например, следующим

...

// Это код клиента.
// Использовать свойство Instance
Singleton obj1 = Singleton.Instance;

// Проверить obj1 на равенство null
if (obj1 != null)
{
  obj1.D = 25;
  obj1.Print("obj1");
}
else
  WriteLine("obj1 == null");

// Попытка создать другой экземпляр класса
Singleton obj2 = Singleton.Instance;

if (obj2 != null)
{
  obj2.D = 77;
  obj2.Print("obj2");
}
else
  WriteLine("obj2 == null");

...

 


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