## 32.适配器模式
适配器模式是一种可以适应各种需求的类。 假设我们有一个名为`Animal`的类,并且根据它必须适应的方式,如果它需要像狗一样表现,则需要说“ woof!”; 如果它需要表现得像只猫,则必须说“喵!” 等等。 然后我们可以编写如下代码:
```rb
# without_adapter.rb
class Animal
def speak(kind)
puts case kind
when :dog then "woof!"
when :cat then "meow!"
when :owl then "hoo!"
end
end
end
Animal.new.speak(:dog)
```
输出量
```rb
woof!
```
但是深思熟虑,这段代码好吗? 每次我需要使这种动物表现得像新动物一样,我需要更改`Animal`类。 如果我编写了`Animal`类,可以在不更改其原始代码的情况下更改其行为,该怎么办? 欢迎使用适配器模式。
现在看下面的代码 [animal.rb](code/design_patterns/animal.rb) 。 现在让我不解释它,而是跳到其实现
```rb
# animal.rb
class Animal
module Adapter
module Dog
def self.speak
puts "woof!"
end
end
module Cat
def self.speak
puts "meow!"
end
end
end
def speak
self.adapter.speak
end
def adapter
return @adapter if @adapter
self.adapter = :dog
@adapter
end
def adapter=(adapter)
@adapter = Animal::Adapter.const_get(adapter.to_s.capitalize)
end
end
```
因此,在下面的程序 [adapter.rb](code/design_patterns/adapter.rb) 中,我们使用了在 [animal.rb](code/design_patterns/animal.rb) 中编写的类`Anaimal`
```rb
# adapter.rb
require_relative "animal.rb"
animal = Animal.new
animal.speak
animal.adapter = :cat
animal.speak
```
Output
```rb
woof!
meow!
```
在这里,我们首先调用`animal.speak`并在其上打印`woof!`,然后通过命令`animal.adapter = :cat`告诉它像猫一样适应,然后再次调用`animal.speak`并在其上打印`meow`。 好吧,这是如何工作的。
现在,让我们分析 [animal.rb](code/design_patterns/animal.rb) 中的代码。 这里我们有一个名为`Animal`的类,其中有一个函数来设置适配器,如下所示
```rb
def adapter=(adapter)
@adapter = Animal::Adapter.const_get(adapter.to_s.capitalize)
end
```
当我们将适配器的名称作为`Symbol`传递时,请注意代码`adapter.to_s.capitalize`,如果我们将其作为`:cat`传递,则它将转换为`Cat`,这只是`Animal::Adapter`中模块的名称 ]。 当我们在`Animal::Adapter.const_get(….)`<sup class="footnote">[[66](#_footnotedef_66 "View footnote.")]</sup> statement. So we have set the `@adapter`中获得常数时,这将加载到`@adapter`中。
现在让我们看一下`Animal`类如何根据我们设置的适配器调用相应的`speak`方法。 假设`@adapter`加载了常量`Animal::Adapter::Cat`,现在该函数
```rb
def adapter
return @adapter if @adapter
self.adapter = :dog
@adapter
end
```
在`return @adapter if @adapter`中返回常量。 因此,在`animal.adapter = :cat`之后的`animal.speak`语句中,它将在`Animal::Adapter::Cat`中加载`speak`函数。 因此,当其被调用时,它返回`meow!`。
现在,以这种方式编码类别`Animal`的优点是我们可以将其扩展到不同的动物,而无需修改原始类别。 换句话说,可以使其适应新情况。 请参见下面的 [adapter_2.rb](code/design_patterns/adapter_2.rb) 中的代码。 我们在`Animal::Adapter`中放置了一个名为`Owl`的新模块,当我们使用`animal.adapter = :cat`将适配器设置为 owl 并调用`animal.speak`时,得到的响应为`hoo!`
```rb
# adapter_2.rb
require_relative "animal.rb"
class Animal
module Adapter
module Owl
def self.speak
puts "hoo!"
end
end
end
end
animal = Animal.new
animal.adapter = :owl
animal.speak
```
Output
```rb
hoo!
```
- 前言
- 红宝石
- 先决条件
- 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.策略模式
- 赞助商
- 捐
- 人们怎么说
- 版权
- 取得这本书