策略模式的原则:把继承改为组合

问题背景

假设你们公司要开发一个Duck应用,Duck分为两种,CityDuck和WildDuck,他们都能Display()和Quack()。于是你想到了类的继承。

游戏开发中的策略模式 - 图1

初代完成了。这时候又有新需求。

需求一:添加Fly行为。

很简单,又用继承。

需求二:添加更多的Duck(如RubberDuck等)

当你尝试用继承的时候,Bug产生了,因为RubberDuck是不能Fly的。

于是你产生了两个想法。

想法一:

于是你想到了把RubberDuck的Fly方法override一遍

想法二:

你想到interface,于是你把能飞的鸭子实现接口flyable。

但当你添加更多Duck的时候,你发现维护起来并不容易,因为每个Duck你都要实现一遍。

最终,你想到了:

把继承变为组合,面向接口编程而不是面向实现编程。

问题解决

鸭子飞是一种行为,我们定义为接口FlyBehaviour,其中有方法Fly.

然后鸭子飞这种行为有两种实现,一种为FlyWithWings,另一种为FlyWithNoWings,我们把他们称为算法

于是我们只需要给能飞的鸭子封装FlyWithWings的算法,不能飞的鸭子封装FlyWithNoWings的算法,这样咋爱我们调用的时候就可以直接调用FlyBeHaviour.Fly()了.

这就是策略模式

策略模式

定义:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。

如何解决:将这些算法封装成一个一个的类,任意地替换。

关键代码:实现同一个接口。

应用实例: 1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。 2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。 3、JAVA AWT 中的 LayoutManager。

优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。

游戏开发中的策略模式 - 图2

板子

  1. using System;
  2. namespace StrategePattern
  3. {
  4. //抽象算法类
  5. abstract class Strategy
  6. {
  7. //抽象算法方法
  8. public abstract void AlgorithmInterface();
  9. }
  10. class ConcreteStrategyA : Strategy
  11. {
  12. public override void AlgorithmInterface()
  13. {
  14. Console.WriteLine("算法A实现");
  15. }
  16. }
  17. class ConcreteStrategyB : Strategy
  18. {
  19. public override void AlgorithmInterface()
  20. {
  21. Console.WriteLine("算法B实现");
  22. }
  23. }
  24. class ConcreteStrategyC : Strategy
  25. {
  26. public override void AlgorithmInterface()
  27. {
  28. Console.WriteLine("算法C实现");
  29. }
  30. }
  31. class Context
  32. {
  33. Strategy m_strategy;
  34. //封装算法
  35. public Context(Strategy theStrategy)
  36. {
  37. m_strategy = theStrategy;
  38. }
  39. public void ContextInterface()
  40. {
  41. m_strategy.AlgorithmInterface();
  42. }
  43. }
  44. class Program
  45. {
  46. static void Main(string[] args)
  47. {
  48. Context context;
  49. context = new Context(new ConcreteStrategyA());
  50. context.ContextInterface();
  51. context = new Context(new ConcreteStrategyB());
  52. context.ContextInterface();
  53. context = new Context(new ConcreteStrategyC());
  54. context.ContextInterface();
  55. }
  56. }
  57. }

游戏实例——多阵营攻击流程

图片来自《设计模式与游戏完美开发》

游戏开发中的策略模式 - 图3