据我了解:在Ruby中,当我们不需要状态时,我们使用模块而不是类。如果只是一个需要输入的函数,则会产生输出。
某些设计模式取决于继承,例如template design pattern。
我正在制作一个爬网库,它将链接作为输入并产生一个包含数据的对象。
它不需要状态,因此模块似乎更适合我而不是类。我还需要使用模板设计模式,因为我正在使用不同的算法来生成具有相同结构的数据。我需要使用继承来实现模板设计模式,但是我不需要状态。它只是从网站返回数据。
实现设计模式是否是使用类(用于继承)的充分理由?在这种情况下的最佳做法是什么?
答案 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