我最近几天一直在处理这个基于Factory模式的类,你可以在这里注册类,给它们提供唯一的名称,然后使用它们来动态创建对象。我的课看起来像这样:
{
"languages": [
{
"id": 1,
"language": { "name": "Spanish" },
"proficiency": {
"level": "native_or_bilingual",
"name": "Native or bilingual proficiency"
}
},
{
"id": 2,
"language": { "name": "English" },
"proficiency": {
"level": "full_professional",
"name": "Full professional proficiency"
}
},
{
"id": 3,
"language": { "name": "Japanese" },
"proficiency": {
"level": "elementary",
"name": "Elementary proficiency"
}
}
]
}
但是我有一些问题,这些问题出现在我写测试的时候。
module AisisWriter
class ClassFactory
class << self
undef_method :new
attr_accessor :registered_objects
def register(class_name, klass, params = nil)
if !params.nil? && !params.is_a?(Array)
raise ArgumentError, "Params must be an array."
end
if registered?(class_name)
raise ArgumentError, "Class name already registered."
end
@registered_object[class_name] = {:class_name => klass, :params => !params.nil? ? params.flatten : nil}
end
def registered?(class_name)
if @registered_object.nil?
return false
end
@registered_object.include? class_name
end
def create(class_name, params = nil)
if !params.nil? && !params.is_a?(Array)
raise ArgumentError, "Params must be an array."
end
if !registered?(class_name)
raise ArgumentError, "Class does not exist in the registered classes."
end
klass = @registered_object[class_name]
if !params.nil
klass[:class_name].new(params.flatten)
else
flass[:class_name].new(*klass[:params])
end
end
end
end
end
函数中: register(...)
这失败是因为@registered_object[class_name] = {:class_name => klass, :params => !params.nil? ? params.flatten : nil}
为零。我如何只初始化一次?在php中我会写一个@registered_object
方法,并说如果设置了类实例,不要再设置它,而我们设置类实例时也设置其他只需要设置一次的变量。我会在这里使用getInstance()
方法吗?
get_instance
设置为@registered_object
一次,那么我可以这样做:{}
ruby是否支持这个?这里的基础是确保在调用此类时,我们检查AisisWriter::ClassFactory.get_instance.register(...)
是否为nil,如果是,则将其设置为@register_object
的新实例
如果有一个更容易的解决方案,我很满意。
答案 0 :(得分:5)
你可以做到
def registered_object
@registered_object ||= {}
end
然后拨打registered_object
而不是@registered_object
。
这是一个常见的Ruby习语。这意味着:
如果@registered_object是假的,则将其设置为{}。
答案 1 :(得分:0)
如果你想要一个真正的单件工厂,那么Ruby有Singleton module可以帮助你!
您可以像这样定义您的课程:
module AisisWriter
class ClassFactory
include Singleton
attr_accessor :registered_objects
def initialize
@registered_object = {}
end
def register(class_name, klass, params = nil)
raise ArgumentError, "Class name already registered." if registered? class_name
@registered_object[class_name] = {:class_name => klass, :params => params}
end
def registered?(class_name)
@registered_object.key? class_name
end
def create(class_name, params = nil)
raise ArgumentError, "Class does not exist in the registered classes." unless registered? class_name
klass = @registered_object[class_name]
klass[:class_name].new *Array(params || klass[:params])
end
end
end
这提供了一种#initialize
方法,您可以在其中设置所有单例状态,但::new
不可调整,如您所料。相反,您使用::instance
。
然后你就像使用它一样:
AisisWriter::ClassFactory.instance.register(...)
AisisWriter::ClassFactory.instance.create(...)
首次调用#instance
时,工厂只会被实例化一次。