我有一些这样的课程:
class Word
def initialize (file_name)
load_file(file_name)
end
def pick_first_word(score)
#get first word
end
private
def load_file(file_name)
#load the file
end
end
class MyClass < SomeOther
def initialize (file_name)
@word = Word.new(file_name)
end
def pick
@word.pick_first_word
end
#some other code
end
dosomething = MyClass.new("words.txt")
dosomethingelse = MyClass.new("movies.txt")
所以我有一个Word
的类,它读入一个文件并选择第一个单词。就像我希望有另一个课程,比如Movies
,它将拥有自己的load_file
和pick_first_word
实现。我希望这由我发送到MyClass
的文件类型控制。
问题
更改initialize
中MyClass
方法的好方法是什么,以便根据我发送的文件类型启动正确的类。我可以通过文件名上的if / else来实现,但这似乎不是很容易扩展。
除了将initialize
的{{1}}方法更改为此内容之外,还有更好的方法吗?
MyClass
此实现似乎不具有可扩展性。
答案 0 :(得分:0)
这都是权衡问题 - 在这种情况下,您需要足够的复杂性来处理合理数量的案例。
如果只有两个选项,我认为if语句看起来很好。 'case' statement(也称为switch语句)可以是DRYer,您可能想明确说出“movie.txt”,例如
@word = (case file_name
when "word.txt"
Word
when "movie.txt"
Movie
else
raise "Unknown file name #{file_name}"
end).new(file_name)
或提取class_for_file_name
方法,如果你不喜欢在parens中添加一个case语句,即使它非常有趣。
如果您的多态类集变大,您可能会从查找表中获得更多的里程数:
class_for_file_name = {
"word.txt" => Word,
"movie.txt" => Movie,
"sandwich.txt" => Sandwich,
}
@word = class_for_file_name[file_name].new(file_name)
当然,也许你过分简化,你真的想要打开文件扩展名,而不是文件 name ,你可以用{{1 }}
你甚至可以变得更加漂亮,并询问每个具体类是否处理这个文件名;这感觉更多OO - 它将关于foos的知识放在Foo类中 - 但可以说更复杂:
File.extname(file_name)
BTW这个问题或多或少符合名为Abstract Factory的设计模式;您可能想要查看它,看看它的任何分析是否能激发您的灵感。
答案 1 :(得分:-1)
尝试使用FileMagic库。
gem install ruby-filemagic
示例:
require 'filemagic'
type = FileMagic.new.file file_name