модуль 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 для повышения исключений TypeErrors, чтобы предотвратить клонирование или дублирование.
Singleton и Marshal
По умолчанию, #_dump(depth) модуля Singleton возвращает пустую строку. Десериализация по умолчанию удалит информацию о состоянии, например, переменные экземпляра из экземпляра. Классы, использующие 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"
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
Константы
- VERSION
Публичные методы класса
# File lib/singleton.rb, line 171
По умолчанию вызывает instance(). Переопределите для сохранения состояния синглтона.
# File lib/singleton.rb, line 175
Возвращает экземпляр синглтона.
Приватные методы класса
# File lib/singleton.rb, line 154
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 162 def included(klass) super klass.private_class_method :new, :allocate klass.extend SingletonClassMethods Singleton.__init__(klass) end
Публичные методы экземпляра
# File lib/singleton.rb, line 108 def _dump(depth = -1) '' end
По умолчанию, не сохраняет состояние при сериализации.
# File lib/singleton.rb, line 98
def clone
raise TypeError, "can't clone instance of singleton #{self.class}"
end Вызывает исключение TypeError для предотвращения клонирования.
# File lib/singleton.rb, line 103
def dup
raise TypeError, "can't dup instance of singleton #{self.class}"
end Вызывает исключение TypeError для предотвращения дублирования.
Ruby Core © 1993–2020 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.