модуль Singleton
Модуль Singleton реализует паттерн Singleton.
Использование
Для использования Singleton, включите модуль в свой класс.
class Klass include Singleton # ... end
Это гарантирует, что может быть создан только один экземпляр класса Klass.
a,b = Klass.instance, Klass.instance a == b # => true Klass.new # => NoMethodError - new is private ...
Экземпляр создаётся при первом вызове Klass.instance().
class OtherKlass
include Singleton
# ...
end
ObjectSpace.each_object(OtherKlass){}
# => 0
OtherKlass.instance
ObjectSpace.each_object(OtherKlass){}
# => 1
Это поведение сохраняется при наследовании и клонировании.
Реализация
Это достигается следующим образом:
-
Сделать Klass.new и Klass.allocate закрытыми.
-
Переопределить Klass.inherited(sub_klass) и Klass.clone() для обеспечения сохранения свойств Singleton при наследовании и клонировании.
-
Предоставить метод Klass.instance(), который возвращает один и тот же объект каждый раз при вызове.
-
Переопределить Klass._load(str) для вызова Klass.instance().
-
Переопределить Klass#clone и Klass#dup для выброса исключения TypeError, чтобы предотвратить клонирование или дублирование.
Singleton и Marshal
По умолчанию #_dump(depth) в Singleton возвращает пустую строку. Сериализация по умолчанию удаляет информацию о состоянии, например, переменные экземпляра и состояние taint, из экземпляра. Классы, использующие Singleton, могут предоставить пользовательские методы _load(str) и _dump(depth) для сохранения части предыдущего состояния экземпляра.
require 'singleton'
class Example
include Singleton
attr_accessor :keep, :strip
def _dump(depth)
# this strips the @strip information from the instance
Marshal.dump(@keep, depth)
end
def self._load(str)
instance.keep = Marshal.load(str)
instance
end
end
a = Example.instance
a.keep = "keep this"
a.strip = "get rid of this"
a.taint
stored_state = Marshal.dump(a)
a.keep = nil
a.strip = nil
b = Marshal.load(stored_state)
p a == b # => true
p a.keep # => "keep this"
p a.strip # => nil
Публичные методы класса
# File lib/singleton.rb, line 171
По умолчанию вызывает instance(). Переопределите для сохранения состояния синглтона.
Закрытые методы класса
# File lib/singleton.rb, line 152
def append_features(mod)
# help out people counting on transitive mixins
unless mod.instance_of?(Class)
raise TypeError, "Inclusion of the OO-Singleton module in module #{mod}"
end
super
end # File lib/singleton.rb, line 160 def included(klass) super klass.private_class_method :new, :allocate klass.extend SingletonClassMethods Singleton.__init__(klass) end
Публичные методы экземпляра
# File lib/singleton.rb, line 107 def _dump(depth = -1) '' end
По умолчанию не сохраняет состояние при сериализации.
# File lib/singleton.rb, line 97
def clone
raise TypeError, "can't clone instance of singleton #{self.class}"
end Выбрасывает TypeError для предотвращения клонирования.
# File lib/singleton.rb, line 102
def dup
raise TypeError, "can't dup instance of singleton #{self.class}"
end Выбрасывает TypeError для предотвращения дублирования.
Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.