设计模式-适配器模式示例

明白了!我会通过一个更简单、更直观的例子来说明适配器模式的作用,帮助你更清楚地理解其背后的设计思想。

示例:适配器模式的简化版

假设我们有一个 Bird 类,表示一种鸟类,它有一个 fly 方法。现在我们还想支持一个新的 ToyDuck 类,表示玩具鸭子,它并不具有飞行的能力,但是我们希望能够在同样的接口下调用 fly 方法(比如通过 fly() 来播放玩具鸭子的声音)。在这种情况下,我们可以使用适配器模式来适配 ToyDuck 类,使其能够适配 Bird 接口。

1. 定义原始接口和实现类

首先定义一个原始接口 Bird 和实现类 Sparrow,表示普通的鸟:

# 定义 Bird 接口
class Bird:
    def fly(self):
        pass

# 实现类:普通的鸟(麻雀)
class Sparrow(Bird):
    def fly(self):
        print("Sparrow is flying")

在这个例子中,Sparrow 是一种普通的鸟,能飞。

2. 定义玩具鸭子类

现在,定义一个 ToyDuck 类,它没有飞行的能力,只是一个玩具,不能直接调用 fly 方法:

class ToyDuck:
    def squeak(self):
        print("ToyDuck is squeaking")

ToyDuck 类没有 fly 方法,它只有 squeak 方法。

3. 创建适配器

接下来,创建一个适配器类 ToyDuckAdapter,它实现了 Bird 接口并使用 ToyDuck 类的方法 squeak 来模拟飞行行为:

class ToyDuckAdapter(Bird):
    def __init__(self, toy_duck):
        self.toy_duck = toy_duck

    def fly(self):
        self.toy_duck.squeak()  # 适配:用 squeak 模拟飞行

ToyDuckAdapter 实现了 Bird 接口,并在 fly 方法中调用了 ToyDucksqueak 方法,模拟了飞行行为。

4. 客户端代码

在客户端代码中,既可以使用 Sparrow 直接飞行,也可以通过 ToyDuckAdapter 来适配 ToyDuck

# 创建 Sparrow 实例
sparrow = Sparrow()
sparrow.fly()  # 正常飞行

# 创建 ToyDuck 实例
toy_duck = ToyDuck()
toy_duck_adapter = ToyDuckAdapter(toy_duck)
toy_duck_adapter.fly()  # 适配后模拟飞行(发出 squeak 声音)

输出结果

Sparrow is flying
ToyDuck is squeaking

解释:

  1. Sparrow 类:直接实现了 Bird 接口,具有 fly 方法,代表普通的鸟类。
  2. ToyDuck 类:没有实现 Bird 接口,它只有一个 squeak 方法,用来模拟玩具鸭子的叫声。
  3. ToyDuckAdapter 类:通过适配器实现了 Bird 接口,将 ToyDucksqueak 方法适配为 fly 方法。通过适配器,我们可以用 fly() 来替代玩具鸭子的 squeak(),让它看起来像是“飞行”了。

为什么不直接修改接口实现?

  • 保持原有接口的独立性:我们没有修改 Bird 接口和 Sparrow 类,也没有直接改变 ToyDuck 类的设计。适配器模式将玩具鸭子与鸟类接口解耦,使得原有类不需要被修改。
  • 避免破坏现有代码:如果直接修改 ToyDuck 类来实现 fly 方法,可能会引入不必要的复杂性,尤其是如果 ToyDuck 已经有了其他的行为(如 squeak),我们只想让它适配 Bird 接口而不去修改其核心行为。
  • 扩展性:适配器模式让我们可以在不修改现有类的前提下,为 ToyDuck 等类提供新的接口实现,使得它们能够在现有系统中工作。如果以后有新的类需要适配,我们可以继续创建新的适配器类,而不必修改现有的类。

总结

适配器模式的关键在于将不兼容的接口进行转换,让我们能够在不修改原有类的基础上,增加新的功能或使它们与现有系统兼容。这样,我们的系统设计更加灵活,并且能够应对变化时不容易破坏现有的功能。


文章标签:

评论(0)