这是我从《Head First 设计模式》这本书中学习到的第一个设计模式-策略模式。这本书的内容还是挺有趣的值得推荐。话不多说,进入正题。
首先谈一下策略模式的价值所在,书中是以设计鸭子的例子来讲解的。我这里主要说下我的理解。
在一些类中,某些行为是比较活跃的。比如一个Person类,这个类有一个say方法,表示人说话的行为,但是实际生活中,有些人说话比较快,有些人说话比较慢,有些人不会说话,那么怎样来设计Person类中say这个方法呢?你可能会想,新建一些子类,子类覆盖Person类的say方法来达到说话不一致的目的。如果又出现一种人说话不快不慢是不是又要新建一个子类呢?嗯这你可能觉得还不怎么麻烦,你还能接受。但是如果需求改变,需要为Person类新增加一个eat方法,但是有些人吃荤有些人吃素。这种情况下你还会用继承去实现子类么?
为了应对需求的改变,我们在设计类的时候一定要考虑扩展性、可维护性等。在书中我学到了第一个设计原则:“找出应用中可能需要变化之处,把他们独立出来不要和那些不变化代码混在一起”。再来看看我们设计的Person类。我们可以将say方法单独提取出来,进行单独设计。下面我记录下我设计Personl类的主要设计思路。
1:新建person类将可能变化的say方法交给接口SayBehaviour的实现类去实现。在Person类中生成SayBehaviour的setter方法,用于动态设置say的实现方式。
public class Person {
private String name;
private int age;
private SayBehaviour sayBehaviour;
public void say(){
sayBehaviour.say();
}
public SayBehaviour getSayBehaviour() {
return sayBehaviour;
}
public void setSayBehaviour(SayBehaviour sayBehaviour) {
this.sayBehaviour = sayBehaviour;
}
}
2 新建一个SayBehaviour接口并定义say方法
public interface SayBehaviour {
void say();
}
3 (可选) 新建一个SayBehaviourUtils 工具类,帮助say方法做一些辅助处理
public class SayBehaviourUtils {
protected void preSay(){
System.out.println("SayBehaviourUtils:我是say方法的工具类,我可以帮助说话这个方法做一些辅助工作。");
};
}
4 新建三个表示不同说话方式的类
public class NoSay extends SayBehaviourUtils implements SayBehaviour{
@Override
public void say() {
preSay();
System.out.println("no say");
}
}
public class QuickSay extends SayBehaviourUtils implements SayBehaviour{
@Override
public void say() {
preSay();
System.out.println("say quickly");
}
}
public class SlowSay extends SayBehaviourUtils implements SayBehaviour{
@Override
public void say() {
preSay();
System.out.println("say slowly");
}
}
5 新建一个测试类测试动态设置人的说话方式
public class StrategyTest {
public static void main(String[] args){
Person person1 = new Person();//定义一个人
person1.setSayBehaviour(new QuickSay());//动态设置这个人说话的方式
person1.say();
Person person2 = new Person();//定义一个人
person2.setSayBehaviour(new SlowSay());//动态设置这个人说话的方式
person2.say();
Person person3 = new Person();//定义一个人
person3.setSayBehaviour(new NoSay());//动态设置这个人说话的方式
person3.say();
//神奇的是 如果person2遇到一个神医,治疗后person2会说话了而且说话还很快那么你可以在下面插入一条语句
person3.setSayBehaviour(new QuickSay());
person3.say();
}
}
输出结果:
SayBehaviourUtils:我是say方法的工具类,我可以帮助说话这个方法做一些辅助工作。
say quickly
SayBehaviourUtils:我是say方法的工具类,我可以帮助说话这个方法做一些辅助工作。
say slowly
SayBehaviourUtils:我是say方法的工具类,我可以帮助说话这个方法做一些辅助工作。
no say
SayBehaviourUtils:我是say方法的工具类,我可以帮助说话这个方法做一些辅助工作。
say quickly
SayBehaviourUtils:我是say方法的工具类,我可以帮助说话这个方法做一些辅助工作。
say slowly
SayBehaviourUtils:我是say方法的工具类,我可以帮助说话这个方法做一些辅助工作。
no say
SayBehaviourUtils:我是say方法的工具类,我可以帮助说话这个方法做一些辅助工作。
say quickly
这个例子为say方法单独设计了一个接口,通过不同的实现类实现这个接口去表示say方法的不同行为,在通过person的setSayBehaviour这个方法动态设置say方法的表现形式,来表达这个人说话的方式。你可以在此基础上设计Person类eat方法的不同变现形式。