策略模式的目的是为了动态的设计对象的行为。
比如说,新倩女幽魂游戏中的红衣女刀客【RedSwordsMan】有两种移动的方式:
1、做任务时,骑马移动
2、和自己的伴侣玩耍时,步行移动
ok,肯定还有其他的移动方式,但是现在我就想到了这两种,所以这里设计的时候要方便以后拓展。
怎么实现呢?
我刚学面向对象的时候是这么写的——抽象类【human】
public abstract class human{
private String name;
private ing rank;
...
public abstract void moving(){
}
}
【做任务时骑马的女刀客】
public class human01 extends human{
private String name;
private ing rank;
...
public void maving(){
System.out.println("本大侠的移动方式是骑马");
}
}
【和伴侣秀恩爱时步行的女刀客】
public class human02 extends human{
private String name;
private ing rank;
...
public void maving(){
System.out.println("本大侠的移动方式是步行");
}
}
然后以后可能有了战斗时跑动的女刀客,再写一个类…挺麻烦的是吧。而且这里的女刀客仅仅是移动方式不同,她的名字,等级都是相同的,没必要再加一个对象呀,这不符合客观事实!【设计者所做的设计应该是和大多数人的行为方式一致,比如我们拿到一个工具经过几次试验就知道怎么用,因为我们就是大多数人。不然这个设计就是失败的。】
ok,我们用策略模式来解决这个问题
见UML图
见代码
//怎么移动?抽象成为一个接口!
public interface Moving {
public void moving();
}
//骑马移动【实现类】
public class HorseMoving implements Moving {
@Override
public void moving() {
System.out.println("本大侠是骑马移动的");
}
}
//步行移动【实现类】
public class WalkMoving implements Moving {
@Override
public void moving() {
System.out.println("本大侠是步行移动的");
}
}
//女刀客的抽象类,策略模式体现在下面的 moingway 接口引用。
public abstract class Human {
private String name;
private int rank;
private Moving movingway;//动态的为角色设置移动方式
public Human() {
}
public Human(String name, int rank) {
this.name = name;
this.rank = rank;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getRank() {
return rank;
}
public void setRank(int rank) {
this.rank = rank;
}
public Moving getMovingway() {
return movingway;
}
public void setMovingway(Moving movingway) {
this.movingway = movingway;
}
public void redSwordsManMoving(){
movingway.moving();
}
}
//女刀客的实现类
public class RedSwordsMan extends Human {
public RedSwordsMan(String name, int rank){
super(name, rank);
setMovingway(new WalkMoving());//女刀客的默认移动方式
}
}
没错,策略模式就是如此简单。这里的【如何移动】的实现就是策略。如果我想添加一个战斗跑动的移动方式只需要再写一个实现Moving接口的类就可以了。
策略模式的缺点是什么? 你需要知道所有的策略才能更好的动态的改变对象的行为。
比如Java Swing中的布局管理器
GridBagLayout gridBagLayout = new GridBagLayout();//一种布局方式,网格组布局。
JPanel jPanel = new JPanel();//面板容器
jPanel.setLayout(gridBagLayout);//面板容器动态的设置自己的布局方式
除了网格组布局还有很多种布局方式,我不是Java类的设计者,所以我用的时候就需要查资料——布局方式的种类。如果我遗漏了一种布局方式,那我很可能就没有选到最合适自己的【策略】。