[Java基础] 设计模式之策略模式

写在前面

作者简介:鲸海鹿林

博客主页:鲸海鹿林的主页

名言警句:keep calm and carry on

        本系列参照HeadFirst系列设计模式这本书,换言之,是 HeadFirst设计模式这本书的读书笔记,让我们一起学习吧!

策略模式(Strategy Pattern)

先从简单的模拟鸭子说起

但是,可怕的问题发生了......

思考原因

 尝试解决

新的问题 

软件开发的一个不变真理

​编辑 先把问题归零

分开变化和不会变化的地方

设计鸭子的行为 

实现鸭子的行为

整合鸭子的行为

新的疑惑

测试Duck的代码

​编辑动态设定行为

封装行为的大局观

“有一个”可能比“是一个”更好


策略模式(Strategy Pattern)

策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式可以让算法的变化独立于使用算法的客户。

关于策略模式,没有特别难以理解的,算是设计模式的入门级别 ,本文就以 HeadFirst设计模式上的例子介绍了。

先从简单的模拟鸭子说起

 根据需求,设计好了类图。

 之后,该公司主管认为可以加一些创新,要让鸭子能飞起来。Joe想着,只要在Duck这个超类中增添fly()方法便可以,这样继承自基类的具体实现类便都能实现fly()方法了。

但是,可怕的问题发生了......

领导很快给Joe打了电话:Joe,我正在股东大会上,刚刚看了一下展示,有很多“橡皮鸭子”在屏幕上飞来飞去,这是你在开玩笑吗?你可能要开始去逛逛Monster.com了……(Monster.com是美国最大的求职网站)

Joe听后心想:好吧!我承认在设计上是有一些小的失误,但是,他们怎么不把这当成一种“特色”,不还挺有趣的吗……

思考原因

Joe忽略了一件事:并非所有的鸭子都会飞,也并非所有的鸭子都会呱呱叫,就比如橡皮鸭,它不会飞,它是吱吱叫而非呱呱叫。

对代码的局部修改,影响的可能不仅仅是局部。

 尝试解决

Joe首先想到的是继承,通过覆盖基类的fly()方法来阻止橡皮鸭起飞,同时,他又想到了另一个问题,如果之后加入诱饵鸭——木头假鸭,既不会飞,也不会叫......

 Joe意识到了继承可能并不是答案,他刚刚拿到了来自主管的备忘录,希望以后每六个月更新一次产品(至于更新的方法,他们还未定下),这样,规格便会常常改变,每当有新的鸭子子类出现,他都要被迫去检查并可能需要覆盖fly()和quark()……这将是无止尽的噩梦。

因此,他需要一个更为清晰的方法,让某些鸭子类型可飞或者可叫。

Joe想到:我可以把fly()从超类中提取出来,放入一个Flayable接口中,这样,只有会飞的鸭子才会去实现此接口,同样的方法,也可以设计一个Quackable接口,因为并非所有鸭子都会叫。

新的问题 

 如果有一种建立软件的方法,好让我们可以用一种对既有的代码影响最小的方式来修该软件就好了......

软件开发的一个不变真理

 先把问题归零

 我们已知,使用继承无法很好地解决所有的问题,因为鸭子的行为在其子类中是不断变化的,而让所有的子类都具有这些行为又是不恰当的;使用接口在一开始时似乎还不错,可以去解决问题,但是Java接口不具备有实现代码,使用接口无法重用代码。

无论何时需要去修改某个行为,都必须在每一个定义该行为的类中去修改它,一不小心就会导致新的错误。设计原则中有一个正好适用于这种情况:

 把会变化的部分取出并“封装”起来,好让其他部分不会受到影响。下面是时候把鸭子的行为从Duck类中取出了。

分开变化和不会变化的地方

 我们知道Duck类内的fly和quack方法会随着鸭子的不同而改变,现在,我们将它们取出来,组建一组新的类来代表每一种行为。

设计鸭子的行为 

 有了这些目标需要实现,接着看看第二个设计原则:

 我们利用接口来代表每个行为,例如:FlyBehavior和QuakBehavior,而行为的每个实现都将实现其中的一个接口。

 从现在开始,鸭子的行为将被放在分开的类中,此类专门提供某行为接口的实现,这样,鸭子类便不需要知道行为的实现细节。

 

实现鸭子的行为

 这么设计,可以让飞行和呱呱叫的动作被其他的对象复用,因为这些行为已经与鸭子类无关了。而我们也可以新增一些行为,不会影响到既有的行为类i,也不会影响“使用”到飞行行为的鸭子类。

整合鸭子的行为

 关键在于,现在鸭子会将飞行和呱呱叫的行为委托别的类处理,而非使用定义在Duck类中(子类)中的呱呱叫和飞行方法。

做法如下:

新的疑惑

测试Duck的代码

动态设定行为

在鸭子里建立了一堆动态的功能没有用到,太可惜了!假设我们想在鸭子子类中通过设定方法来设定鸭子的行为,而不是在鸭子的构造器内实例化。

封装行为的大局观

好,我们已经深入研究了鸭子模拟器的设计,该是时候将头探出水面,呼吸空气了。现在来看看整体的格局:

“有一个”可能比“是一个”更好

 

 这是一个很重要的技巧,使用了我们的第三个设计原则:

如你所见,使用组合建立系统具有很大的弹性,不仅可将算法族封装成类,更可以“在运性时动态地改变行为”,只要组合的行为对象符合正确的接口标准即可。

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鲸海鹿林

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值