Одиночка (шаблон проектирования)

Материал из Seo Wiki - Поисковая Оптимизация и Программирование
Перейти к навигацииПерейти к поиску

Одиночка, (англ. Singleton)порождающий шаблон проектирования.

Цель

Гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа. Существенно то, что можно пользоваться именно экземпляром класса, так как при этом во многих случаях становится доступной более широкая функциональность. Например, к описанным компонентам класса можно обращаться через интерфейс, если такая возможность поддерживается языком.

Плюсы

  • контролируемый доступ к единственному экземпляру;
  • уменьшение числа имён;
  • допускает уточнение операций и представления;
  • допускает переменное число экземпляров;
  • большая гибкость, чем у операций класса.

Минусы

  • Глобальные объекты могут быть вредны для объектного программирования, в некоторых случаях приводя к созданию немасштабируемого проекта.

Применение

  • должен быть ровно один экземпляр некоторого класса, легко доступный всем клиентам;
  • единственный экземпляр должен расширяться путем порождения подклассов, и клиентам нужно иметь возможность работать с расширенным экземпляром без модификации своего кода
Файл:Singleton classdia.png

Пример реализации

Пример Java 1.5: с отложенной инициализацией

<source lang="java"> class Singleton {

   private volatile static Singleton instance;
   private Singleton() {}
   public static Singleton getInstance() {
       if (instance == null) {
           synchronized (Singleton.class) {
               if (instance == null) {
                   instance = new Singleton();
               }
           }
       }
       return instance;
   }

} </source>

Пример Java 1.5: Class holder on JVM start initialization

<source lang="java"> public class Singleton {

  protected Singleton() {}
  private static class SingletonHolder {  
     public static Singleton instance = new Singleton();  
  }  
  
  public static Singleton getInstance()  {  
     return SingletonHolder.instance;  
  }  

} </source>

Пример Java 1.5: Enum singleton

<source lang="java"> public enum SingletonEnum {

  INSTANCE;  
  public void someMethod() {  
     ***
  }  
     
  public void anotherMethod() {  
     ***
  }  

} </source>

Пример Python

<source lang="python"> >>> class Singleton(object):

       obj = None                           # Атрибут для хранения единственного экземпляра
       def __new__(cls,*dt,**mp):           # класса Singleton.
          if cls.obj is None:               # Если он еще не создан, то
             cls.obj = object.__new__(cls,*dt,**mp) # вызовем __new__ родительского класса
          return cls.obj                    # вернем синглтон

... >>> obj = Singleton() >>> obj.attr = 12 >>> new_obj = Singleton() >>> new_obj.attr 12 >>> new_obj is obj # new_obj и obj - это один и тот же объект True

</source>

Пример C++

Возможная реализация на C++ (известная как синглтон Мейерса), где одиночка представляет собой статический локальный объект (важно: это решение не потоко-безопасно и приводится только для того, чтобы показать как устроен шаблон, а не для реального использования в крупномасштабных программных проектах. Кроме того, данная реализация не обеспечивает невозможность создать еще один экземпляр класса).

<source lang="cpp">

template<typename T> class Singleton
{
 
  public:
    static T& Instance()
    {
        static T theSingleInstance; // у класса T есть конструктор по умолчанию
        return theSingleInstance;
    }
};
 
class OnlyOne : public Singleton<OnlyOne>
{
    //.. интерфейс класса
};

</source>

Пример C#

<source lang="csharp">

/// generic Singleton<T> (потокобезопасный с использованием generic-класса и с отложенной инициализацией)

/// <typeparam name="T">Singleton class</typeparam> public class Singleton<T> where T : class, new() {

 /// Защищенный конструктор по умолчанию необходим для того, чтобы
 /// предотвратить создание экземпляра класса Singleton
 protected Singleton() { }
 /// Фабрика используется для отложенной инициализации экземпляра класса
 private sealed class SingletonCreator where S : class, new()
 {
   private static readonly S instance = new S();
   public static S CreatorInstance
   {
     get { return instance; }
   }
 }
 public static T Instance
 {
   get { return SingletonCreator<T>.CreatorInstance; }
 }

}

/// Использование Singleton public class TestClass : Singleton<TestClass> {

   public string TestProc()
   {
       return "Hello World";
   }

}

</source>

Так же можно использовать стандартный вариант потокобезопасной реализации Singleton с отложенной инициализацией:

<source lang="csharp"> public class Singleton {

 protected Singleton() { }
 private sealed class SingletonCreator
 {
   private static readonly Singleton instance = new Singleton();
   public static Singleton Instance { get { return instance; } }
 }
 public static Singleton Instance
 {
   get { return SingletonCreator.Instance; }
 }

} </source>

Пример PHP 4

<source lang="php"> <?php class Singleton {

function Singleton( $directCall = true ) {

       if ( $directCall ) {
           trigger_error("Нельзя использовать конструктор для создания класса Singleton. 
                          Используйте статический метод getInstance ()",E_USER_ERROR);
       }
       //TODO: Добавьте основной код конструктора здесь
   }
   function &getInstance() {
       static $instance;
       if ( !is_object( $instance ) ) {
           $instance = new Singleton( false );
       }
       return $instance;
   }

} ?> </source>

Пример PHP 5

<source lang="php">

<?php

class Singleton {

 // object instance
 private static $instance;

 private function __construct() {}

 private function __clone() {}

 public static function getInstance() {
   if (self::$instance === null) {
     self::$instance = new self;
   }
   return self::$instance;
 }

 public function doAction() {
   ...
 }

}

//usage Singleton::getInstance()->doAction(); ?> </source>

Пример на Delphi

Файл:SingletonInTogether.jpg
Синглтон на диаграмме классов

<source lang="delphi">

unit Unit1;

interface

type
  TSingleton = class
  strict private
    constructor Create;

  class var
    FInstance: TSingleton;

  public
    class function GetInstance: TSingleton;
  end;

implementation

constructor TSingleton.Create;
begin
  inherited;
end;

class function TSingleton.GetInstance: TSingleton;
begin
  if FInstance = nil then
  begin
    FInstance := TSingleton.Create();
  end;
  Result := FInstance;
end;

end.

</source>

Пример на языке Io

‎<source lang="Io">

Singleton := Object clone Singleton clone := Singleton

</source>


Пример на языке Ruby

<source lang="Ruby"> class Singleton

   def self.new
       @instance ||= super
   end

end </source>

В стандартную библиотеку (Ruby 1.8 и выше) входит модуль Singleton, что позволяет создавать синглтоны еще проще:

<source lang="Ruby"> require 'singleton' class Foo

   include Singleton

end a = Foo.instance # Foo.new недоступен, для получения ссылки на (единственный)

                # экземпляр класса Foo следует использовать метод Foo#instance

</source>

Пример на Common Lisp

<source lang="lisp"> (defclass singleton-class () ;;метакласс, реализующий механизм синглтона

 ((instance :initform nil)))

(defmethod validate-superclass ((class singleton-class) (superclass standard-class))

 t) ;;Разрешаем наследование классов-синглтонов от обычных классов

(defmethod validate-superclass ((class singleton-class) (superclass singleton-class))

 t) ;;Разрешаем наследование классов-синглтонов от других классов-синглтонов

(defmethod validate-superclass ((class standard-class) (superclass singleton-class))

 nil) ;;Запрещаем наследование обычных классов от синглтонов

(defmethod make-instance ((class singleton-class) &key)

 (with-slots (instance) class
   (or instance (setf instance (call-next-method)))))

(defclass my-singleton-class ()

 () 
 (:metaclass singleton-class))

</source>

Пример на Perl

<source lang="perl"> package Singleton;

use strict;

my $singleton;

sub new {

   my $class = shift();
   return $singleton ||= bless(sub {1}, $class);

}

1; </source>

Пример на ActionScript3

<source lang="actionscript"> package {

class Singleton {

private static var instance:Singleton;

public static function getInstance() : Singleton { if (instance == null) { instance = new Singleton(new Singletoniser()); } return instance; }

public function Singleton(singletoniser : Singletoniser) { if (singletoniser == null) { throw new Error("Singleton is a singleton class, use getInstance() instead."); } } } }

class Singletoniser { }</source>

Пример на JavaScript с инкапсуляцией

В данном примере используется механизм замыканий, предотвращающий возможную модификацию приватных членов псевдокласса. <source lang="javascript"> function Singleton() {

   var foo = 'bar'; //локальная переменная
   function instantiate() { //локальная функция
       this.fun = function() { //эта функция доступна извне
           alert(foo);
       }
       return this;
   }
   function SingletonInstance() {
       return instantiate();
   }
   return new SingletonInstance();

}

var object1 = Singleton(); //фактически получаем экземпляр SingletonInstance object1.fun(); //выведет 'bar' - это возможно благодаря замыканию var object2 = Singleton();

alert(object1===object2); //выведет 'true' - переменные ссылаются на один и тот же объект alert(Singleton.foo); //выведет 'undefined', т.к. локальная переменная недоступна alert(object1.foo); //выведет 'undefined' </source>

Без использования сокрытия переменных есть более простое решение, основанное на том, что функция Singleton является объектом. Минусом является возможность изменения св-ва instance вне класса: <source lang="javascript"> function Singleton() { if (!Singleton.instance) { Singleton.instance = this; } else { return Singleton.instance; // должен возвращаеться object } // код конструктора располагается после проверки }

var object1 = new Singleton(); var object2 = new Singleton();

alert(object1===object2); // выведет 'true' - переменные ссылаются на один и тот же объект alert(object1.instance); // выведет 'undefined', т.к. instance имеется в контрукторе object1, но не в его прототипе </source>

См. также

Ссылки


порождающие шаблоны проектирования
абстрактная фабрика | строитель | фабричный метод | прототип | одиночка | отложенная инициализация


bg:Сек (шаблон) ca:Patró singleton cs:Singleton de:Singleton (Entwurfsmuster) en:Singleton pattern es:Singleton fr:Singleton (patron de conception) he:תבנית Singleton it:Singleton ja:Singleton パターン ko:싱글턴 패턴 ml:സിംഗള്‍ട്ടണ്‍ പാറ്റേണ്‍ nl:Singleton (informatica) pl:Singleton (wzorzec projektowy) pt:Singleton sv:Singleton th:ซิงเกิลตันแพตเทิร์น tr:Tekillik Kalıbı uk:Одинак (шаблон проектування) zh:单例模式

Если вам нравится SbUP.com Сайт, вы можете поддержать его - BTC: bc1qppjcl3c2cyjazy6lepmrv3fh6ke9mxs7zpfky0 , TRC20 и ещё....