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

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

Перейти к: навигация, поиск

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

Содержание

Цель

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

Плюсы

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

Минусы

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

Применение

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

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

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

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;
    }
}

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

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

Пример Java 1.5: Enum singleton

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

Пример 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

Пример C++

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

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

Пример C#

/// 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<S> 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";
    }
}

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

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; }
  }
 
}

Пример PHP 4

<?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;
    }
}
?>

Пример PHP 5

 <?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();
?>

Пример на 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.

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

Singleton := Object clone
Singleton clone := Singleton


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

class Singleton
    def self.new
        @instance ||= super
    end
end

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

require 'singleton'
class Foo
    include Singleton
end
a = Foo.instance # Foo.new недоступен, для получения ссылки на (единственный)
                 # экземпляр класса Foo следует использовать метод Foo#instance

Пример на Common 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))

Пример на Perl

package Singleton;
 
use strict;
 
my $singleton;
 
sub new {
    my $class = shift();
 
    return $singleton ||= bless(sub {1}, $class);
}
 
1;

Пример на ActionScript3

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 {
}

Пример на 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'

Без использования сокрытия переменных есть более простое решение, основанное на том, что функция Singleton является объектом. Минусом является возможность изменения св-ва instance вне класса:

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, но не в его прототипе

См. также

Ссылки


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


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:单例模式

Личные инструменты

Served in 0.445 secs.