对模块使用设计模式

时间:2018-07-23 21:59:08

标签: ruby design-patterns

据我了解:在Ruby中,当我们不需要状态时,我们使用模块而不是类。如果只是一个需要输入的函数,则会产生输出。

某些设计模式取决于继承,例如template design pattern

我正在制作一个爬网库,它将链接作为输入并产生一个包含数据的对象。

它不需要状态,因此模块似乎更适合我而不是类。我还需要使用模板设计模式,因为我正在使用不同的算法来生成具有相同结构的数据。我需要使用继承来实现模板设计模式,但是我不需要状态。它只是从网站返回数据。

实现设计模式是否是使用类(用于继承)的充分理由?在这种情况下的最佳做法是什么?

1 个答案:

答案 0 :(得分:0)

  

在Ruby中,当我们不需要状态时,我们使用模块而不是类。如果只是一个需要输入的函数,则会产生输出。

这是模块的一个使用。模块的另一用途是提供其他语言称为“特征”的功能集,可以将这些功能集插入到任何类中而无需继承。这通常可以包括存储状态。

请确保保持灵活性,Ruby是一种非常灵活的语言。


  

它不需要状态,因此模块似乎更适合我而不是类。我还需要使用模板设计模式,因为我正在使用不同的算法来生成具有相同结构的数据。

设计模式提供了模式来解决某些一般性问题,而不是必须严格遵守的一组规则。许多语言都是用C ++或Java编写的,它们都是以类为中心的语言,并且需要适应其他语言。

对于您而言,重要的是界面保持不变。无需创建整个抽象类,只需定义一个接口即可。某些语言具有正式接口,例如Rust或Java。 Ruby没有。相反,它使用duck-typing。基本上,如果它具有所需的方法并且说它可以按需要工作,请使用它。

module DoThatThing
  module ThisProvider
    def link_to_object(link)
      ...code to convert a link to ThisProvider into an object...

      return object
    end
  end

  module ThatProvider
    def link_to_object(link)
      ...code to convert a link to ThatProvider into an object...

      return object
    end
  end
end

现在无论您有DoThatThing::ThisProvider还是DoThatThing::ThatProvider,都可以使用相同的内容。

obj = provider_module.link_to_object(link)

如果确实愿意,您可以implement formal abstract modules in Ruby,但是在Ruby 中通常是浪费的精力,并且与在Ruby中的工作方式大相径庭。 >(使用其他语言,绝对要创建一个界面)。

相反,请通过测试强制执行此操作。 RSpec shared examples或测试系统的类似功能是实现此目的的好方法。您编写了一组测试,该测试应适用于DoThatThing的任何实现,并针对DoThatThing的所有实现运行它们。

RSpec.shared_examples 'DoThatThing' do
  ...shared tests for any DoThatThing...
end


RSpec.describe DoThatThing::ThisProvider do
  include_examples "DoThatThing"

  ...tests specific to ThisProvider...
end

RSpec.describe DoThatThing::ThatProvider do
  include_examples "DoThatThing"

  ...tests specific to ThatProvider...
end