其实针对策略模式我在之前已经了解过了,现在再写一遍是因为我今天在回顾策略模式的时候发现我并没有将这个模式很好地使用起来,所以今天我再回顾一次,并结合我在实际工作过程中的某些地方,来回顾哪些地方我是可以更好地优化的,并且这个周末我正准备着手进行工作中代码的重新优化
首先来讲策略模式的总要点,策略模式的核心,是多用组合,少用继承,可以将不同的算法族做到灵活的替换
既然讲到了多用组合,少用继承,那么这种写法势必要与继承做一个对比,那么我在这里定义一个
比如我们想要写一只狗,狗会叫,会摇尾巴,同时这只狗也可以是一只泰迪狗,或者狼狗,也会叫,会摇尾巴
那么这时,如果我们用继承的方式来写就是这样,首先定义一个狗的父类
<span style="font-size:14px;">public abstract class Dog {
/**
* 狗叫
*/
public abstract void bite();
/**
* 摇尾巴
*/
public abstract void wagTail();
}</span>
定义好了之后,我们首先需要实现一只狼狗,那么就是这样实现
<span style="font-size:14px;">public class WolfDog extends Dog{
public static final String TAG = "tag";
/**
* 狼狗叫
*/</span>
<span style="font-size:14px;"><span style="white-space:pre"> </span>@Override
public void bite(){
Log.i(TAG, "wolf dog bite");
}
/**
* 摇尾巴
*/</span>
<span style="font-size:14px;"><span style="white-space:pre"> @Override</span>
public void wagTail(){
Log.i(TAG, "wolf dog wagtail");
}
}</span>
那这时候我们再需要一只泰迪狗的时候你会发现什么,发现泰迪狗是没有尾巴的,所以他不会摇尾巴,但是叫的时候是一样的,都是汪汪叫,那么在狼狗中叫的方法,我们得复制一遍再放到泰迪狗中去,而摇尾巴的方法,我们只需要空实现即可
但是,继续扩展下去呢,橡皮狗、电子狗,各种各样的,有些是叫声一样的,有些是不一样的,对于一样的,我们可以父类直接写成汪汪叫,针对不是汪汪叫的单独实现,但是,还是有一个问题,如果衍生的狗里面,有一堆是喵喵叫的呢?
针对这种方式,当然我们也可以写成封装好的工具,直接在不同狗里面调用实现就可以了,但是也还是有一种情况,
,就是如果我们研发了一只超级电子狗,见人说人话,见狗说狗话,这种实时变化的时候我们该怎么办?
那么这种时候,就需要我们用到策略模式,那么如果用策略模式来写这只狗我们该怎么写
首先,我需要写两个接口
<span style="font-size:14px;">/**
* 叫的接口
*/
public interface BiteBehavior{
public void bite();
}
/**
* 摇尾巴的接口
*/
public interface WagTailBehavior{
public void wagTail();
}</span>
然后,我需要实现一下这两个接口
<span style="font-size:14px;">/**
* 汪汪叫
*/
public class WangBite implements BiteBehavior{
@Override
public void bite() {
Log.i(TAG, "wang bite");
}
}
/**
* 喵喵叫
*/
public class MiaoBite implements BiteBehavior{
@Override
public void bite() {
Log.i(TAG, "miao bite");
}
}
/**
* 一般的摇尾巴
*/
public class NormalWagTail implements WagTailBehavior{
@Override
public void wagTail() {
Log.i(TAG, "normal wagtail");
}
}
/**
* 没有尾巴的摇尾巴
*/
public class NoTail implements WagTailBehavior{
@Override
public void wagTail() {
}
}</span>
在实现了接口之后,我们就可以开始狗的定义了
<span style="font-size:14px;">public class Dog {
private BiteBehavior mBiteBehavior;
private WagTailBehavior mWagTailBehavior;
public Dog(){
mBiteBehavior = new WangBite();
mWagTailBehavior = new NormalWagTail();
}
/**
* 叫
*/
public void bite(){
mBiteBehavior.bite();
}
/**
* 摇尾巴
*/
public void wagTail(){
mWagTailBehavior.wagTail();
}</span>
<span style="font-size:14px;">}</span>
可以看到,与继承不同的是,这种模式的实现方式是使用接口代替继承,这种方式有继承的优点
如果这时候我们实现狼狗类,只需要继承叫和摇尾巴的接口写成新的方法即可,并且可以达到方法复用
那么,刚才也说道,如果我们需要一只超级智能狗,见人说人话,见狗说狗话,那么这种方式可以实现吗,当然可以
我们只需要添加一个方法
public void setBiteBehavior(BiteBehavior behavior){
mBiteBehavior = behavior;
}
这样就实现了实时的转换,可以说,这种模式还是很不错的
那么又到了思考时间:
从目前看来,这种模式的优点是:有了继承的优点,并且扩展了可以灵活配置改变某个功能实现方式的优点
但是也存在一个缺点,那就是当项目比较大时,类将会变得很多,当然这个也可以通过自己的控制来控制
当结合我们在实际中的项目的时候,还有一个问题,我们希望一些方法可以灵活地配置到不同的地方,但是,当这些实现的方法需要不同的参数时,我们要如何写好这个不同参数的传递与准备,如果我们将准备的参数封装为一个对象传递进来,那么也会面临这个对象的参数众多,到时使用时针对不同的实现类要去设置不同的参数,反而变得更加麻烦,所以,这里的这个模式的使用,还需要在写之前考虑清楚
不过还是有一句话的收获:有一个,总比是一个好