设计模式
设计模式是对常见设计的总结和抽象,既是一种解决问题的思路,同时也是一种提高沟通效率的工具。本文将介绍一些常见的设计模式。
策略模式
让我们考虑一个名为 SimDuck
的模拟鸭子游戏,这一游戏用于展示各种不同鸭子来愉悦心情。这个应用程序的主要需求即模拟各种类型的鸭子,例如野鸭、红头鸭、诱饵鸭等。这些鸭子都有一些共同的行为,例如游泳、飞行等,但是它们也有一些不同的行为,例如呱呱叫、吱吱叫等。有时,我们需要为某些鸭子添加新的行为(即变化),例如潜水。我们如何设计这个应用程序,使得它既能够保持灵活性,又能够避免代码重复呢?
继承并重写(override
)是一种解决方案。所有鸭子都继承 BaseDuck
父类,那么在添加新的行为时就可以在父类中添加新的方法,然后在子类中重写这个方法。但是这种方法有一个缺点,即我们需要为未添加这一行为的鸭子重写这个方法,这样会导致代码重复。另一种解决方案是使用接口,即为每一种行为定义一个接口,然后在每一个鸭子类中实现这些接口。但是这种方法也有一个缺点,即如果我们需要为某些鸭子添加新的行为,那么我们需要修改所有添加这一行为的鸭子子类,这也不是一个完美的方法。
我们重新从设计的角度考虑,可以发现这些方式都没有从变化的角度出发。先前的设计都是直接在实现部分进行修改,而并没有为变化的部分进行封装。可以看出,易变的部分是鸭子的行为,而不是鸭子的类型。因此,我们可以将鸭子的各类行为抽象出来,然后将其封装到几个类中。这样,当我们需要为某些鸭子添加新的行为时,我们只需要修改这个行为抽象类即可。在不同的鸭子类中,我们只要按需引入这些行为抽象类,然后调用它们的方法即可。这一设计是依赖倒置原则、开闭原则和合成复用原则的体现。
如果将鸭子看作是一个上下文,而将鸭子的行为看作是一个策略,那么,这一设计模式就是经典的策略模式(Strategy
或 Policy
的命名。
策略模式的结构如下:
- 策略接口
Strategy
:定义了所有支持的算法的公共接口。通常是一个接口或抽象类。 - 具体策略
ConcreteStrategy
:实现了策略接口的具体算法。
策略模式的特点有:
- 可维护性和可复用性强,易于扩展。
- 策略可以在运行时进行替换。
- 然而,客户需要对策略有了解,知晓每一个策略的优缺点,从而选择合适的策略。