今天看了《设计模式》的第一章——策略模式。感觉自己懂了一点,但不知道自己在实际中会用不。
定义一系列的算法,把他们一个一个的封装起来,并使它们可以相互替换。该模式使得算法可独立使用它的客户而变换。
——《设计模式》GOF
看了上面那句话可能不知所云。下面我们来看一个例子。在例子中学习是最快的。如果要你做一个模拟鸭子的游戏:游戏中会出现各种鸭子,所有的鸭子都能游泳戏水,有的鸭子能飞有的鸭子不能飞。请用OO技术设计好这个鸭子项目。
对于一个没学过设计模式但学过OO的人可能这样分析:这个鸭子项目你可能认为,所有鸭子都能游泳的话,那么所有鸭子游泳的行为是一样的。而有的鸭子不能飞有的鸭子能飞,则应该把这个行为抽象成一个接口。注意这个接口的行为是一个可变化的。则这个项目中有一个超类(所有的鸭子都要继承这个类)和一个接口(包含一个飞的方法)。
只要继承上面的Duck类和接口就可以设计一个模拟的鸭子了。
如下图:
但你想过没你这样做的话,每设计出一个鸭子类型就要实现一个方法,这样就会出现大量重复的代码。因为飞只有能飞和不能飞两种行为。
这时你可能会想到既然飞只有两种就应该把两种方法实现出来,用两个类分别实现IFyBehavior接口。在我们设计鸭子类型的时候继承它们。嘿嘿,不错不错,离目标进了一步。两个类如图下;
但这样做的话一个模拟鸭子就要继承两个类(超类Duck和实现了接口的类)。请想一想,如果这个项目要扩展,还要加上鸭子的叫声,有的叫声大有的小。那模拟鸭子又要加一个继承的类。如果更多呢。那我们模拟鸭子的继承类就更多了。但是c#中只能继承一个类。所以,我们应该把要需的那些变化的行为接口放在超类Duck中。
这样的话鸭子类型只要继承超类Duck就可以了。新Duck代码如下:
2 {
3 public IFlyBehavior Iflybehavior;
4 public void performFly()
5 {
6 Iflybehavior.fly();
7 }
8 public Duck()
9 {
10
11 }
12
13 public void swim()
14 {
15
16 }
17
18 public void display()
19 {
20
21 }
22 }
模拟鸭子类型如下:
2 {
3 public MallardDuck()
4 {
5 Iflybehavior = new FlyWithWings();
6 }
7 }
测试模拟鸭子的代码:
2 {
3 public static void main(string [] args)
4 {
5 Duck mallard = new MallardDuck();
6 mallard.performFly();
7 }
8
9 }
到此一个策略模式就走完了。它有三个设计原则:
1.找出应用中可能需要变化之处,把它们独立出来,不要i和那些不需要变化的代码混在一起。
2.针对接口编程,而不是针对实现编程。
3.多用组合,少用继承。(组合即是那些变动的行为抽象出来的接口)
现在再回过头来看看策略模式的定义。可以看出算法族就是那些可以变动的行为(我的理解)。把可以变动的行为封装起来更利于代码的扩展和修改。