модуль 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 объявлены как private.
-
Переопределяются методы Klass.inherited(sub_klass) и Klass.clone() для сохранения свойств
Singletonпри наследовании и клонировании. -
Предоставляется метод Klass.instance(), который каждый раз возвращает один и тот же объект.
-
Переопределяется метод Klass._load(str) для вызова Klass.instance().
-
Переопределяются методы Klass#clone и Klass#dup для повышения исключения TypeError, предотвращая клонирование и дублирование.
Singleton и Marshal
По умолчанию Singleton#_dump(depth) возвращает пустую строку. Сериализация по умолчанию удалит информацию о состоянии, например, переменные экземпляра из экземпляра. Классы, использующие 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
Публичные методы класса
# File lib/singleton.rb, line 169
По умолчанию вызывает instance(). Переопределите для сохранения состояния синглтона.
# File lib/singleton.rb, line 173
Возвращает экземпляр синглтона.
Приватные методы класса
# 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 106 def _dump(depth = -1) '' end
По умолчанию, не сохраняет состояние при сериализации.
# File lib/singleton.rb, line 96
def clone
raise TypeError, "can't clone instance of singleton #{self.class}"
end Вызывает TypeError для предотвращения клонирования.
# File lib/singleton.rb, line 101
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.