多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
## 36.策略模式 无论你是否意识到自己是一名出色的战略家。 早上醒来时,你会去喝咖啡,如果没有咖啡粉,你可能会喝杯茶或热巧克力或牛奶。 你开车去上班或上学,如果某条路受阻,则采取另一种方式。 在工作中,你需要考虑向老板呈现的方式,是否使老板心情愉快的方式,以便你可以谈论事实或掩盖事实。 策略无处不在,你只是没有注意到它。 你每次都会根据环境 &lt;sup class="footnote"&gt;[ [68](#_footnotedef_68 "View footnote.") ]&lt;/sup&gt; 不断采用新策略。 在计算世界中,如果我们能够根据传递的标志/参数告诉一段代码动态运行不同的算法,则这种编码称为策略模式。 让我们看下面的示例 [strategy_pattern.rb](code/design_patterns/strategy_pattern.rb) : ```rb ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 ```rb | ``` # strategy_pattern.rb module NewsFormatter class Text def self.format(data) seperator = "\n* " seperator + data.join(seperator) end end class HTML def self.format(data) html = [] html &lt;&lt; "&lt;ul&gt;" data.each { &#124;datum&#124; html &lt;&lt; "&lt;li&gt;#{datum}&lt;/li&gt;" } html &lt;&lt; "&lt;/ul&gt;" html.join "\n" end end end class NewsGenerator def self.generate(data, formatter) formatter.format(data) end end news = [ "You are reading I Love Ruby.", "There is water down below in the oceans.", "There is air up above our heads.", "Even people in space report their is air up above their heads.", "Even bald people have air up above their heads." ] puts "News As HTML:" puts "\n" puts NewsGenerator.generate(news, NewsFormatter::HTML) puts "\n\n" puts "News As Text:" puts "\n" puts NewsGenerator.generate(news, NewsFormatter::Text) puts "\n\n" ```rb | ``` 输入并执行 输出量 ```rb News As HTML: <ul> <li>You are reading I Love Ruby.</li> <li>There is water down below in the oceans.</li> <li>There is air up above our heads.</li> <li>Even people in space report their is air up above their heads.</li> <li>Even bald people have air up above their heads.</li> </ul> News As Text: * You are reading I Love Ruby. * There is water down below in the oceans. * There is air up above our heads. * Even people in space report their is air up above their heads. * Even bald people have air up above their heads. ``` 现在让我们分析代码。 查看以下几行(29-35): ```rb news = [ "You are reading I Love Ruby.", "There is water down below in the oceans.", "There is air up above our heads.", "Even people in space report their is air up above their heads.", "Even bald people have air up above their heads." ] ``` 在这里,我们声明一个名为`news`的数组,并在其中填充新闻项。 然后在第 39 行中,有以下语句`puts NewsGenerator.generate(news, NewsFormatter::HTML)`,其输出如下: ```rb <ul> <li>You are reading I Love Ruby.</li> <li>There is water down below in the oceans.</li> <li>There is air up above our heads.</li> <li>Even people in space report their is air up above their heads.</li> <li>Even bald people have air up above their heads.</li> </ul> ``` 注意,对于`NewsGenerator`类中的`generate`方法,我们提供了两个参数作为输入,第一个是数据,在这种情况下,数据是`news`数组,其中包含新闻列表。 下一个参数是`NewsFormatter::HTML`,这是打印时要遵循的策略。 现在看第 24 行的 generate 方法,它看起来像这样: ```rb def self.generate(data, formatter) formatter.format(data) end ``` 在这里,我们将`formatter`作为第二个参数,即本例中的`NewsFormatter::HTML`,并将其传递给`data`作为参数,从而对其调用`format`方法。 因此,程序控制转到第 12 行,该行位于模块`NewsFormatter`内,并进入类`HTML`中的方法`self.format`中,你可以在此处看到代码段 ```rb module NewsFormatter .... class HTML def self.format(data) html = [] html << "<ul>" data.each { |datum| html << "<li>#{datum}</li>" } html << "</ul>" html.join "\n" end end end ``` 在该函数中,我们神奇地将其转换为 HTML 无序列表 &lt;sup class="footnote"&gt;[ [69](#_footnotedef_69 "View footnote.") ]&lt;/sup&gt; ,然后将其返回。 当我们调用`puts NewsGenerator.generate(news, NewsFormatter::Text)`时,会发生相同的事情,但是由于我们通过了不同的策略`NewsFormatter::Text`,因此这段代码得以执行: ```rb module NewsFormatter class Text def self.format(data) seperator = "\n* " seperator + data.join(seperator) end end .... end ``` 那就是调用了模块`NewsFormatter`中类`Text`中的函数`self.format`,该函数会产生纯文本输出,如项目符号,因此你将看到以下输出: ```rb * You are reading I Love Ruby. * There is water down below in the oceans. * There is air up above our heads. * Even people in space report their is air up above their heads. * Even bald people have air up above their heads. ```