## 36.策略模式
无论你是否意识到自己是一名出色的战略家。 早上醒来时,你会去喝咖啡,如果没有咖啡粉,你可能会喝杯茶或热巧克力或牛奶。 你开车去上班或上学,如果某条路受阻,则采取另一种方式。 在工作中,你需要考虑向老板呈现的方式,是否使老板心情愉快的方式,以便你可以谈论事实或掩盖事实。 策略无处不在,你只是没有注意到它。 你每次都会根据环境 <sup class="footnote">[ [68](#_footnotedef_68 "View footnote.") ]</sup> 不断采用新策略。
在计算世界中,如果我们能够根据传递的标志/参数告诉一段代码动态运行不同的算法,则这种编码称为策略模式。 让我们看下面的示例 [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 << "<ul>"
data.each { |datum| html << "<li>#{datum}</li>" }
html << "</ul>"
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 无序列表 <sup class="footnote">[ [69](#_footnotedef_69 "View footnote.") ]</sup> ,然后将其返回。
当我们调用`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.
```
- 前言
- 红宝石
- 先决条件
- 1.安装 Ruby
- 2.在线资源
- 3.入门
- 4.比较与逻辑
- 5.循环
- 6.数组
- 7.哈希和符号
- 8.范围
- 9.功能
- 10.可变范围
- 11.类&对象
- 12.安全导航
- 13.打破大型程序
- 14.结构和 OpenStruct
- 15. Rdoc
- 16. Ruby 样式指南
- 17.模块和混入
- 18.日期和时间
- 19.文件
- 20. Proc,Lambda 和块
- 21.多线程
- 22.异常处理
- 23.正则表达式
- 24.宝石
- 25.元编程
- 26.基准
- 27.测试驱动开发
- 28.观察者模式
- 29.模板模式
- 30.工厂模式
- 31.装饰图案
- 32.适配器模式
- 33.单例模式
- 34.复合模式
- 35.建造者模式
- 36.策略模式
- 赞助商
- 捐
- 人们怎么说
- 版权
- 取得这本书