Интернет магазин китайских планшетных компьютеров |
|
Компьютеры - Одиночка (шаблон проектирования) - Пример реализации30 марта 2011Оглавление: 1. Одиночка (шаблон проектирования) 2. Пример реализации Пример на Java 1.5: с отложенной инициализацией
class Singleton {
private volatile static Singleton instance;
private Singleton {}
public static Singleton getInstance {
if {
synchronized {
if {
instance = new Singleton;
}
}
}
return instance;
}
}
Остерегайтесь, это антипаттерн! Пример на Java 1.5: Class holder on JVM start initialization
public class Singleton {
private 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:
def __init__:
super.__init__
cls.instance = None
def __call__:
if cls.instance is None:
cls.instance = super.__call__
return cls.instance
>>> class MyClass:
... __metaclass__ = Singleton
...
>>> a = MyClass
>>> a.attr = 12
>>> b = MyClass
>>> b.attr
12
>>> a is b
True
Пример на C++Возможная реализация на C++, где одиночка представляет собой статический локальный объект. Важным моментом является то, что конструктор класса объявлен как private, что позволяет предотвратить создание экземпляров класса за пределами его реализации. Отметим также, что приведенный пример потоко-небезопасен, для работы с классом из нескольких потоков нужно защитить переменную
class OnlyOne
{
public:
static OnlyOne* Instance
{
if
theSingleInstance=new OnlyOne;
return theSingleInstance;
}
private:
static OnlyOne* theSingleInstance;
OnlyOne{};
};
OnlyOne* OnlyOne::theSingleInstance=NULL;
Пример на C#
/// generic Singleton<T>
/// <typeparam name="T">Singleton class</typeparam>
public class Singleton<T> where T : class
{
/// Защищенный конструктор по умолчанию необходим для того, чтобы
/// предотвратить создание экземпляра класса Singleton
protected Singleton { }
/// Фабрика используется для отложенной инициализации экземпляра класса
private sealed class SingletonCreator<S> where S : class
{
//Используется Reflection для создания экземпляра класса без публичного конструктора
private static readonly S instance = typeof.GetConstructor(
BindingFlags.Instance | BindingFlags.NonPublic,
null,
new Type,
new ParameterModifier).Invoke;
public static S CreatorInstance
{
get { return instance; }
}
}
public static T Instance
{
get { return SingletonCreator<T>.CreatorInstance; }
}
}
/// Использование Singleton
public class TestClass : Singleton<TestClass>
{
private 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 {
if {
trigger_error("Нельзя использовать конструктор для создания класса Singleton.
Используйте статический метод getInstance",E_USER_ERROR);
}
//TODO: Добавьте основной код конструктора здесь
}
function &getInstance {
static $instance;
if ) {
$instance = new Singleton;
}
return $instance;
}
}
//usage
$test = &Singleton::getInstance;
?>
Пример на PHP 5
<?php
class Singleton {
protected static $instance; // object instance
/**
* Защищаем от создания через new Singleton
*
* @return Singleton
*/
private function __construct { /* ... */ }
/**
* Защищаем от создания через клонирование
*
* @return Singleton
*/
private function __clone { /* ... */ }
/**
* Возвращает единственный экземпляр класса
*
* @return Singleton
*/
public static function getInstance {
if ) {
self::$instance = new Singleton;
}
return self::$instance;
}
public function doAction { /* ... */ }
}
//usage
Singleton::getInstance->doAction;
?>
Пример на Delphi
Синглтон на диаграмме классов
В языке Delphi вплоть до недавних версий было невозможно скрыть стандартный конструктор Create, кроме того, отсутствовали поля класса.
unit SingletonUnit;
interface
type
TSingleton = class
private
constructor ActualCreate;
public
constructor Create;
class function GetInstance: TSingleton;
end;
implementation
var
Singleton: TSingleton;
constructor TSingleton.ActualCreate;
begin
inherited Create;
end;
constructor TSingleton.Create;
begin
raise Exception.Create
end;
class function TSingleton.GetInstance: TSingleton;
begin
if Singleton = nil then
Singleton := TSingleton.ActualCreate;
Result := Singleton;
end;
end.
Пример на языке Io Singleton := Object clone Singleton clone := Singleton Пример на языке Ruby
class Singleton
def self.new
@instance ||= super
end
end
В стандартную библиотеку входит модуль Singleton, что позволяет создавать синглтоны еще проще:
require 'singleton'
class Foo
include Singleton
end
a = Foo.instance # Foo.new недоступен, для получения ссылки на
# экземпляр класса Foo следует использовать метод Foo#instance
Пример на Common Lisp
;;метакласс, реализующий механизм синглтона
))
)
t) ;;Разрешаем наследование классов-синглтонов от обычных классов
)
t) ;;Разрешаем наследование классов-синглтонов от других классов-синглтонов
)
nil) ;;Запрещаем наследование обычных классов от синглтонов
&key)
class
))))
)
Пример на VB.NET
Module Program
Sub Main
Dim T1 As Singleton = Singleton.getInstance
T1.Value = 1000
Dim T2 As Singleton = Singleton.getInstance
Console.WriteLine
Console.Read
End Sub
End Module
Public Class Singleton
Public Value As Integer
'Не разрешаем конструктор
Protected Sub New
End Sub
Private NotInheritable Class SingletonCreator
Private Shared ReadOnly m_instance As New Singleton
Public Shared ReadOnly Property Instance As Singleton
Get
Return m_instance
End Get
End Property
End Class
Public Shared ReadOnly Property getInstance As Singleton
Get
Return SingletonCreator.Instance
End Get
End Property
End Class
Пример на Perl
package Singleton;
use strict;
my $singleton;
sub new {
my $class = shift;
return $singleton ||= bless;
}
1;
Пример на ActionScript 3
package
{
public class Singleton
{
private static var INSTANCE:Singleton;
public function Singleton
{
if throw new Error;
}
static public function getInstance:Singleton
{
if INSTANCE = new Singleton);
return INSTANCE;
}
}
}
// internal class for singleton isolation
internal class SingletonKey { }
Пример на CoffeeScriptКлассический подход
class Singleton
instance = undefined
constructor : ->
if
return instance
else instance = @
# Код конструктора
console.assert;
Подход, основанный на возможности доступа к функции из её тела.
class Singleton
init = -> # конструктор как приватный метод класса
# Код конструктора
# ...
# Заменяем конструктор, сохраняя this
init = => @
return @
# Реальный конструктор. Служит для вызова init
# return использовать обязательно, иначе вернёт this
constructor : -> return init.apply
console.assert
Примечание: изменение настоящего конструктора из него самого, т.е constructor : -> Singleton = => @ ничего не даст, т.к. в результирующем JavaScript-коде constructor указывает на локальный конструктор Singleton, а не на класс Singleton. Однако, если использовать пространства имён, то возможен такой вариант:
ns = {}
class ns.Singleton
constructor : ->
# Код конструктора
ns.Singleton = => @
console.assert
Пример на JavaScript с инкапсуляциейМетод, основанный на сокрытии переменных с помощью замыканий. В качестве бонуса - возможность объявлять приватные методы и свойства, которые будут доступны и конструктору и методам "класса".
var Singleton = new function {
var instance;
// Приватные методы и свойства
// ...
// Конструктор
function Singleton {
if
instance = this;
else return instance;
// Публичные свойства
}
// Публичные методы
Singleton.prototype.test = function {};
return Singleton;
}
console.assert;
Без использования сокрытия переменных есть простое решение, основанное на том, что функция Singleton является объектом. Минусом является возможность изменения св-ва __instance вне класса:
function Singleton {
if
Singleton.__instance = this;
else return Singleton.__instance;
// Код конструктора располагается после проверки
}
console.assert;
alert; // 'true' - переменные ссылаются на один и тот же объект
alert; // 'undefined', т.к. __instance является статическим свойством "класса" Singleton
Наиболее короткий вариант. Стоит отметить, что статические свойства "класса" затрутся.
function Singleton {
// Код конструктора
var single = this;
Singleton = function { return single }; // Переопределяем конструктор
}
console.assert;
MooTools классы с соответствующим плагином.
var Singleton = new Class.Singleton({
initialize: function{
// Код конструктора
},
method1: function{
// Динамический метод
}
});
console.assert;
Пример на Objective-CSingleton.h
@interface Singleton : NSObject {
}
+ sharedInstance;
@end
Singleton.m
@implementation Singleton
static Singleton *_sharedInstance = nil;
static void singleton_remover {
if {
;
}
}
+ sharedInstance {
if {
_sharedInstance = init];
// release instance at exit
atexit;
}
return _sharedInstance;
}
@end
Просмотров: 2272
|