开篇
最近开始学习设计模式,Head First这本书很奇怪,和一般地书籍不一样,一开始就一个策略模式。
不过,确实是本好书,但懂得设计模式,不代表你就是可以设计出优美的代码来,毕竟设计模式是实践中来,还是要回到实践中去的~。我打算把这个写成一个系列,作为自己学习的笔记,绝不"太监",也欢迎大家一起来讨论,我毕竟是个初学设计模式的鸟,从前还没设计模式这种概念,总感觉自己的代码很"脏",OK,废话太多了~!
策略模式定义
The Strategy Pattern:a family of algorithms, encapsulates each one,and makes them interchangeable,Strategy lets the algorithm vary indepently from clients that use it.
材料,我就取自书本,重在理解。
让我们从鸭子开始吧~
Joe是一个OO程序员,他上班的公司设计了一个产品—模拟鸭子的游戏,在游戏中,会产生很多的鸭子,有红头,绿头的,瘸腿的等,会一边游泳,一边呱呱叫的。一开始的设计是这样的:

可以派生出很多的不同种类的鸭子,因为每个鸭子都会游泳和呱呱叫,所以,直接由Duck这个抽象基类实现,但种类可能不同,display()方法是抽象的。"很好,很强大"~!但是,最近公司的竞争压力很大,其他公司推出了更好的产品了,那么怎么办?升级产品,扩展产品?OK,最后决定,在这个产品上增加会飞的鸭子,重新夺回市场。我们的Joe又开始工作了。。。
怎么办
增加会飞的鸭子?好简单,我们在Duck类上再添加个fly()的方法,OK,好了~Joe,兴致冲冲地打电话给上司!2天后~,"Joe,你给我进来!"老上司直接吼到,完了,完了?怎么回事,原来是产品在演示的时候,突然出现了"会飞的橡皮鸭子",就是,所有的鸭子都会飞了,但是,橡皮鸭子会飞吗?那,在橡皮鸭子类中,我覆盖调继承下来的fly()方法,使它不在作用,不就可以了~?但是,如果以后再增加个不会叫也不会飞的鸭子呢,是不是也覆盖调继承下来的quck()的方法呢?那么,以后,我又增加些别的什么,是不是都这样做~?Joe,意识到了,有时候继承并不能很完美地解决问题,反而会越来越糟!继承Duck的方法会导致那些缺陷:
- 代码在多个子类中重复
- 运行时候,行为不容易改变(你不可能叫原来不会飞的鸭子,在运行时候会飞了~)
- 很难知道鸭子的所有行为(就是,那么多的鸭子~)
- 改变会牵一发而动全身
继承不行,那接口呢
每次的更新,如果都要这样干,Joe想想都要崩溃了,接口行不行?Joe立刻想到,把fly()方法独立到一个类中,其他同类情况的也一样处理如何?最后设计成这样:
工作完成了??还没呢,大家想象一下,如果,我有几十个鸭子,那要一个一个这样添加,泪奔~!!!那有没有一种方法,既可以很少地更改原来的代码,又可以减少重构的实践?这个时候,就需要设计模式出马了。。。
策略模式
一个设计原则,要牢记:找出应用中可能需要变化之处,把它们独立出来,封装起来,区别那些不变化的部分。

这样设计,我们就不要具体是哪个鸭子实现,只要执行行为方法就行了!所以,在这里定义"接口",FlyBehavior和QuackBehavior,具体是怎么飞,怎么叫的,我们自己扩展到具体的类中,这样,以后要是在增加尖叫的,只要在实现个类(“啊啊”叫):

部分代码,代码没去测试过:
public interface IflyBehavior
{
void fly();
}
public interface IquackBehavior
{
void quack();
}
//具体实现
public class HengFly : IflyBehavior
{
public void fly()
{
//横着飞
}
}
public class ZhuanFly : IflyBehavior
{
public void fly()
{
//转圈地飞
}
}
public class GaGaQuack : IquackBehavior
{
public void quack()
{
//嘎嘎叫
}
}
public class ZhiZhiQuack : IquackBehavior
{
public void quack()
{
//吱吱叫
}
}
//鸭子基类
public abstract class Duck
{
//定义两个字段分别来为表示行为接口,每个鸭子都会引用实现这俩个接口对象
protected IflyBehavior flyBehavior;
protected IquackBehavior quackBehavior;
/*
我们吧会飞和会叫的行为委托给这两个对象,
* 它们的fly()还是quack()都是由具体的实现去执行的,比如,我有个绿头鸭子是嘎嘎叫,
* 那么这个DUCK对象是绿头鸭子,再调用行为是performQuack().它再去调用绿头鸭子的叫法
* 大家仔细想象一下,领悟了吧~
*/
public void performFly()
{
flyBehavior.fly();
}
public void performQuack()
{
quackBehavior.quack();
}
//设置方法,只要调用方法了,就能动态创建对象
public void SetflyBehavoir(IflyBehavior fly)
{
this.flyBehavior = fly;
}
public void SetquackBehavior(IquackBehavior quack)
{
this.quackBehavior = quack;
}
protected void swim()
{
//游泳的代码
}
protected void display()
{
//显示外观
}
}
public class oneDuck : Duck
{
public oneDuck()
{
//调用SetflyBehavoir和SetquackBehavior方法,初始化对象
}
}结尾
策略模式:就是定义一系列的算法方法,并它们都封装起来,使它们都独立起来,并且使它们可以相互替换。该模式使得算法可独立于它们的客户变化。。主要是应对:在软件构建过程中,某些对象使用的算法可能多种多样,经常发生变化。如果在对象内部实现这些算法,将会使对象变得异常复杂,甚至会造成性能上的负担。

浙公网安备 33010602011771号