🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 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! ```