The Strategy Pattern (策略模式)

Joe所在的电脑游戏公司研发了一款游戏软件,模拟池塘中各种鸭子嬉戏(游动并且鸣叫)的场景。软件很受欢迎。

设计一个Duck超 类,各种鸭子都继承这个超类。所有的鸭子都会鸣叫和游水,所以Duck超类实现quack()和swim()方法。由于不同种类的鸭子样子不同,所以 Duck中的display()方法设计为抽象方法。不同的鸭子子类通过实现display方法显示自己的样子。

游戏上市后的次年,竞争越来越激烈。在外出度假一周后,公司高管们决定要对游戏作重大创新,在下周的股东大会上,他们要让股东们“印象深刻”。

高管们觉得,如果鸭子能够飞起来,则能击败同类游戏的竞争者。Joe的上司告诉高管们,Joe可以在一周内搞定,因为他是一个 OO Programmer…



但 是,一周后Joe的经理从股东大会上打来电话…Joe,我在股东大会上,刚刚演示了游戏,他们看到屏幕上有许多橡皮玩具鸭子在飞来飞去,你是不是故意搞 笑?!偶的错,偶忘了不是所有的鸭子都会飞!在Duck中增加一个fly()方法,则它的所有子类就都有飞的能力了。没想到,一个局部的修改产生了非局部 的副作用。
在子类RubberDuck中重写fly()方法,让它什么都不做。还有,橡皮鸭也不会嘎嘎叫,只会吱吱叫,这样quack()方法也要改写。但是,如果考虑再增加打猎用的仿真鸭该怎么办呢?它既不会叫也不会飞,这样又得改写方法了。烦!看来,继承这东西有时也挺烦人的!
公司高层决定每半年就要更新该产品,更新的方式他们还没有想好。。。。。。。。。。。。。。。
必须要有一种清晰的方法,让一部分鸭子(而不是全部)能够飞行和鸣叫。把fly()从Duck中分离出来,设计一个接口Flyable,该接口有一个fly()方法,会飞的鸭子就实现该接口。对quack()也依此处理。


Joe的第二个方案解决了部分问题(不会有会飞的橡皮鸭了),但也完全破坏了代码的重用性(每一种会飞的鸭子都必须实现fly()方法,如果要修改飞行行为,则必须修改每种鸭子的fly()代码,设想有几十种会飞的鸭子)。这从另一个方面增加了维护的难度。


正确的解决方案

现在让我们将鸭子的行为从Duck类中分离出来!
我们已经知道,fly()和quack()是Duck类中不同的ducks的变化部分。我们将这些行为从Duck类中分离出来,对于每一个方法,创建一个类的集合来表示相应的行为。例如:对于fly(),我们建立一个类的集合,分别实现翱翔,俯冲,起飞等。

怎么设计实现鸭子飞行和鸣叫行为的类集合?
首 先,我们需要灵活性。在此之前,正是由于不灵活给我们带来了麻烦。我们希望能够将行为指定给鸭子的某个实例。例如,我们可能希望生成一个野鸭实例,并以某 种飞行行为(例如:翱翔)对它初始化,在这之后,我们就会想能不能动态的改变这只野鸭的行为呢?换句话说,我们应该在Duck类中包含一个设置行为的方 法,使得我们能够在运行时改变野鸭的行为(如:由翱翔变为俯冲)
引入接口
对每类行为,我们用一个接口(interface)来表示。例如:用接口FlyBehavior来表示飞行行为,用接口QuackBehavior来表示鸣叫行为。每一个具体的行为类,是这些接口的一个实现(如:翱翔Hover,俯冲Dive,不飞)。
这样做之后,就不是由Duck类来实现飞行和鸣叫接口了,取而代之的是,我们设置了一组类,他们的任务就是表示某个行为,这些行为类将用来实现上面的接口。

新设计方法与以前的方法的差异
这 种做法与我们以前的做法不同,以前我们或者是用Duck超类,或者是用Duck的子类本身来具体实现(implements)一个接口。后两种做法都使我 们依赖于一个实现,我们被使用这种特定的实现捆住了手脚,要改变鸭子的行为时除了对Duck类或其子类进行修改,增加代码外,别无它法。
在我们新的设计方案中,Duck的子类将使用由接口(FlyBehavior或QuackBehavior)表示的行为,而接口由行为类具体实现,这样,行为的具体实现就不会被固化在Duck的子类中了。

代码列表

1.Duck.java
2.FlyBehavior.java
3.QuackBehavior.java
4.FlyWithWings.java

5.FlyNoWay.java

6.FlyRocketPowered.java
7.MuteQuack.java 8.FakeQuack.java 9.MallardDuck.java 10.ModelDuck.java 11.MiniDuckSimulator.java
The End--------------------!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值