Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
打破Ruby类的枯燥_Ruby_Design Patterns - Fatal编程技术网

打破Ruby类的枯燥

打破Ruby类的枯燥,ruby,design-patterns,Ruby,Design Patterns,我有一些类似的课程: 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 initiali

我有一些类似的课程:

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")

这个实现看起来不是很可伸缩

试试FileMagic库

gem install ruby-filemagic
例如:

require 'filemagic'
type = FileMagic.new.file file_name

这都是一个权衡的问题——在这种情况下,您只需要足够的复杂性来处理合理数量的案例

如果只有两种选择,我认为If语句看起来不错。一个(又称switch语句)可以是DRYer,您可能想显式地说“movie.txt”,例如

或者,如果您不喜欢将case语句放在parens中,那么可以为文件名提取一个
class\u方法,尽管这很有趣

如果您的多态类集变得更大,您可能会从查找表中获得更多好处:

class_for_file_name = {
    "word.txt" => Word, 
    "movie.txt" => Movie, 
    "sandwich.txt" => Sandwich,
}
@word = class_for_file_name[file_name].new(file_name)
当然,可能您过于简单化了,您真的想打开文件扩展名,而不是文件名,您可以通过
file.extname(file\u name)
获得文件扩展名

您还可以更进一步,询问每个具体类是否处理该文件名;这感觉更像是面向对象的——它将关于Foo的知识放在Foo类中——但可以说更复杂:

class Word
  def self.good_for? file_name
    file_name == "word.txt"
  end
end

class Movie
  def self.good_for? file_name
    file_name == "movie.txt"
  end
end

...

def class_for_file_name file_name
  [Word, Movie].detect{|k| k.good_for? file_name}
end    

顺便说一句,这个问题或多或少符合所谓的设计模式;您可能想查看它,看看它的任何分析是否能激发您的灵感。

这似乎是“策略”设计模式的一个很好的候选者:有没有办法检测到与文件本身的差异?没有,没有。但如果有帮助的话,我愿意在传递文件名的同时传递其他内容。文件名甚至可以保留在实际类中
class_for_file_name = {
    "word.txt" => Word, 
    "movie.txt" => Movie, 
    "sandwich.txt" => Sandwich,
}
@word = class_for_file_name[file_name].new(file_name)
class Word
  def self.good_for? file_name
    file_name == "word.txt"
  end
end

class Movie
  def self.good_for? file_name
    file_name == "movie.txt"
  end
end

...

def class_for_file_name file_name
  [Word, Movie].detect{|k| k.good_for? file_name}
end