Вот подход, который я использовал для решения аналогичной проблемы, которым я хотел бы поделиться, если вы или другие люди сочтете его подходящим:
require 'singleton'
class Logger
attr_reader :file_name
def initialize file_name
@file_name = file_name
end
end
class MyLogger < Logger
include Singleton
def self.new
super "path/to/file.log"
end
# You want to make {.new} private to maintain the {Singleton} approach;
# otherwise other instances of {MyLogger} can be easily constructed.
private_class_method :new
end
p MyLogger.instance.file_name
# => "path/to/file.log"
MyLogger.new "some/other/path"
# => ...private method `new' called for MyLogger:Class (NoMethodError)
Я тестировал код в 2.3
,2.4
и 2.5
;более ранние версии могут, конечно, демонстрировать расходящееся поведение.
Это позволяет вам иметь общий параметризованный класс Logger
, который можно использовать для создания дополнительных экземпляров для тестирования или будущих альтернативных конфигураций, при этом определяя MyLogger
какединичный экземпляр этого стандарта соответствует стандартному шаблону Ruby Singleton
.Вы можете разделить методы экземпляра между ними по своему усмотрению.
Ruby's Singleton
автоматически создает экземпляр при первой необходимости, поэтому параметры Logger#initialize
должны быть доступны по требованию в MyLogger.new
, но вы можетеконечно, извлекайте значения из среды или устанавливайте их как MyLogger
переменные экземпляра класса во время конфигурации до того, как экземпляр singleton будет когда-либо использоваться, что согласуется с тем, что экземпляр singleton фактически является глобальным.