策略模式的思考

大虾们见笑了
这是小弟第一次写这种文章
多多指点批评

在HEAD FIRST书中,作者用鸭子的例子来说明策略模式
起初,设计的模型是:有个基类Duck,在基类定了了一个变量:description,用来代表鸭子的外观描述,还定义了一个方法fly().
它的子类Mallard(野鸭),Sarcelle(绿翅鸭),Scaup(白胸鸭)都继承了基类中的变量和方法。
随着业务的深入细化,鸭子需要增加新方法比如blat(),而其又出现了其他类型的鸭子,比如木鸭,塑料鸭,这些玩具鸭子不会fly,但可以blat
这时候就要面临大面积的代码重写
首先:父类中增加了新方法就导致了所有的子类都面临着变动。
其次:有些子类又不具备父类中的所有方法
这就和设计原则中的ocp原则发生了冲突
于是作者提出了策略模式
代码进行了如下的重构:
首先把fly()方法提取出来,作为一个单独的接口IFly,同理blat()方法也作为单独一个接口IBlat
根据鸭子的fly和blat行为分别写实现类
然后在父类中增加2个变量,类型分别为IFlay,IBlat
子类显示父类的fly()方式时,实际上没有独自定义方法,而是根据鸭子的类型调用IFly和IBlat的不同实现
而其为了在运行中改变鸭子的行为,在鸭子子类中增加新2个改变fly和blat行为的方法。setFly(),setBlat()


总结:
虽然初始的设计存着问题。
1.子类必须实现父类的方法,各个子类的fly行为可能相同,这样就无法达到代码的重用了。
2.父类增加新的行为,所有的子类都需要变动

但是在策略模式中,问题2依旧存在,只不过不是给子类增加一个方法,而是必须增加一个新变量

个人感觉,策略模式的精髓在于,把子类中的方法提取出来作为一个接口,与鸭子子类之间形成一种松耦合的关系
通过setFly()方法就可以在运行中动态地改变其行为。

书中说如果方法中存在着if-else这种判断就应用策略模式,这样说有点大,模糊了。反过来我们想想,如果我想在运行中动态
改变对象的行为,是如何实现的。
public void method(String type){
if(type.equal("....")){
....
}else{
....
}
}
那么我们就可以运用策略模式改写
interface IMethod(){
public void method();
}

class MethodOne implements IMethod(){
public void method(){
...
}
}

class MethodTwo implements IMethod(){
public void method(){
...
}
}

public class Test(){
private IMehtod iMethod;
public Test(IMethod iMethod){
this.iMethod = iMethod;
}
public void setMethod(IMethod iMethod){
this.iMethod = iMethod;
}
public void method(){
iMethod.method();
}
public static void main(String args[]){
IMethod methodOne = new MethodOne();
IMethod methodTwo = new MethodTwo();

Test test = new Test(methodOne);
test.method();
if(....){
test.setMethod(methodTwo);
test.method();
}
}
}

把判断前后的处理方式提取成方法的好处就是解耦合,并达到代码的重用
解耦合可以这样理解,如果日后方法的处理方式又有了其他方式,我们就必须修改所有的子类,再增加一层判断
利用策略模式,我们所要做的就是增加一个新的实现类,这样我的工作就大打减少了。而其代码也容易维护了

这里还有个原则,就是子类继承父类的时候,最好不要增加新的方法,这样子类向父类转型的时候就容易丢失方法
如果说子类非要增加一个父类中不存在的方法,那就需要重新审视自己的代码了,看是否可以考虑使用组合关系
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值