最近在学设计模式,正好看到大兵的图片,一时兴起决定用士兵来模拟一下策略模式。好了,下面我们来模拟一下有关士兵的应用场景。
我们知道,每一个士兵都有自己的名字,有军衔,同时有自己的训练内容,也要自我放松,那么我们如何定义这个类呢?首先,我们会想到继承。代码如下:
package cn.bon.pattern.strategy.bean;
public abstract class Soldier {
protected String name;
protected Rank rank;//军衔
public void eat(){
System.out.println("请原谅我这个吃货吧");
}
public void display(){
System.out.println("a solider name:"+name+" with rank:"+rank);
}
public abstract void train();
public abstract void relax();
}
现在我们建立一个士兵类,该士兵类通过跑步训练自己,可以看电视放松自己。
package cn.bon.pattern.strategy.bean;
public class SoldierA extends Soldier{
public SoldierA(String name, Rank rank) {
this.name = name;
this.rank = rank;
}
@Override
public void train() {
System.out.println("跑步");
}
@Override
public void relax() {
System.out.println("看电视");
}
}
看起来还不错,现在我们需要一个新的士兵类,该士兵类通过游泳训练自己,可以唱歌放松自己。
package cn.bon.pattern.strategy.bean;
public class SoldierB extends Soldier{
public SoldierB(String name, Rank rank) {
this.name = name;
this.rank = rank;
}
@Override
public void train() {
System.out.println("游泳");
}
@Override
public void relax() {
System.out.println("唱歌");
}
}
如果我们需要一个士兵类,该类士兵通过跑步训练,通过唱歌放松呢?
package cn.bon.pattern.strategy.bean;
public class SoldierC extends Soldier{
public SoldierC(String name, Rank rank) {
this.name = name;
this.rank = rank;
}
@Override
public void train() {
System.out.println("跑步");
}
@Override
public void relax() {
System.out.println("唱歌");
}
}
如果我们还需要一个游泳训练,看电视放松的士兵类呢?或者是其它训练方式以及其它放松方式?显然,这种设计方式已经让我们开始感到害怕了。这个时候就是策略模式出场的模式了。
策略模式:定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
使用策略模式后,代码如下:
package cn.bon.pattern.strategy.strategy;
public interface TrainStrategy {
void train();
}
package cn.bon.pattern.strategy.strategy;
public interface RelaxStrategy {
void relax();
}
下面来定义我们具体行为实现(算法)类
package cn.bon.pattern.strategy.strategy.impl;
import cn.bon.pattern.strategy.strategy.TrainStrategy;
public class RunningTrainStrategy implements TrainStrategy{
@Override
public void train() {
System.out.println("跑步");
}
}
package cn.bon.pattern.strategy.strategy.impl;
import cn.bon.pattern.strategy.strategy.TrainStrategy;
public class SwimmingTrainStrategy implements TrainStrategy{
@Override
public void train() {
System.out.println("游泳");
}
}
package cn.bon.pattern.strategy.strategy.impl;
import cn.bon.pattern.strategy.strategy.RelaxStrategy;
public class SingingRelaxStrategy implements RelaxStrategy{
@Override
public void relax() {
System.out.println("唱歌");
}
}
package cn.bon.pattern.strategy.strategy.impl;
import cn.bon.pattern.strategy.strategy.RelaxStrategy;
public class WatchingTVRelaxStrategy implements RelaxStrategy {
@Override
public void relax() {
System.out.println("看电视");
}
}
好了,现在我们已经把会变化的部分,训练和放松的行为提炼了出来,看一下如何定义我们的Solider类
package cn.bon.pattern.strategy.bean;
import cn.bon.pattern.strategy.strategy.RelaxStrategy;
import cn.bon.pattern.strategy.strategy.TrainStrategy;
public class Soldier {
private String name;
private Rank rank;//军衔
private TrainStrategy mTrainStrategy;
private RelaxStrategy mRelaxStrategy;
public void setTrainStrategy(TrainStrategy trainStrategy) {
this.mTrainStrategy = trainStrategy;
}
public void setRelaxStrategy(RelaxStrategy relaxStrategy) {
this.mRelaxStrategy = relaxStrategy;
}
public Soldier(String name,Rank rank){
this.name = name;
this.rank = rank;
}
public void eat(){
System.out.println("请原谅我这个吃货吧");
}
public void display(){
System.out.println("a solider name:"+name+" with rank:"+rank);
}
public void train(){
if(mTrainStrategy!=null){
mTrainStrategy.train();
}
}
public void relax(){
if(mRelaxStrategy!=null){
mRelaxStrategy.relax();
}
}
}
客户端测试代码:
package cn.bon.pattern.strategy;
import cn.bon.pattern.strategy.bean.Rank;
import cn.bon.pattern.strategy.bean.Soldier;
import cn.bon.pattern.strategy.strategy.impl.RunningTrainStrategy;
import cn.bon.pattern.strategy.strategy.impl.SingingRelaxStrategy;
public class StrategyTest {
public static void main(String[] args) {
//现在我们需要一个跑步,唱歌的士兵
Soldier soldier = new Soldier("David",Rank.PRIVATE);
soldier.setTrainStrategy(new RunningTrainStrategy());
soldier.setRelaxStrategy(new SingingRelaxStrategy());
soldier.display();
soldier.train();
soldier.relax();
}
}
可以看到, 我们把经常变化的训练和放松行为定义成了独立的接口,在士兵类里我们分别声明了一个训练接口和放松接口的示例变量。我们在Solider中不去关注如何去完成,而是把其中的算法交给具体实现接口的类处理。同时,我们通过 setTrainStrategy(TrainStrategy trainStrategy) 和 setRelaxStrategy(RelaxStrategy relaxStrategy)方法很轻松的指定具体要完成的算法,怎么样,是不是感觉很Cool?
好了,现在我们看下案例的uml图加深一下理解
其中接口和接口实现部分我们称之为算法族。
对策略模式总结如下: