Spec-Zone.ru › Ruby 2.5

модуль 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

Публичные методы класса

_load() Показать исходный код
# File lib/singleton.rb, line 171

По умолчанию вызывает instance(). Переопределите для сохранения состояния синглтона.

Закрытые методы класса

append_features(mod) Показать исходный код
# 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
Вызывает метод суперкласса
included(klass) Показать исходный код
# File lib/singleton.rb, line 160
def included(klass)
  super
  klass.private_class_method :new, :allocate
  klass.extend SingletonClassMethods
  Singleton.__init__(klass)
end
Вызывает метод суперкласса

Публичные методы экземпляра

_dump(depth = -1) Показать исходный код
# File lib/singleton.rb, line 107
def _dump(depth = -1)
  ''
end

По умолчанию не сохраняет состояние при сериализации.

clone() Показать исходный код
# File lib/singleton.rb, line 97
def clone
  raise TypeError, "can't clone instance of singleton #{self.class}"
end

Выбрасывает TypeError для предотвращения клонирования.

dup() Показать исходный код
# 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.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API