设计模式学习笔记——状态模式

定义:

当一个对象内在的状态改变时,允许其改变行为,这个对象看起来像是改变了其类。

状态模式不太好理解,我现在还没有完全理解,这个模式给我的第一印象就是比较乱,给我的感觉好像是两个类互相依赖,①调用②的方法,②调用①的方法,弄的好乱,所以这个状态模式就不用通用类图去描述了,那样会不知所云,还是举一个实际的例子来理解吧。

这个例子是书本上的一个例子,是针对足球队比赛时,根据比分的领先还是落后,来调整其阵型,从而进入相应的状态,其示意图如下:


                                       


其对应的类图如下:

                                                                                  图2  足球对的状态模式类图

解释:可以注意到FootballTeam这个类维护了一个ScoreState对象,表示FootballTeam这个类维护当前的一个状态,通过其中的changeState()方法来切换维护的状态,而改变阵型的方法changeLineUp()这个方法是足球队的行为,它只是调用当前维护状态中的changeLineUp()方法,因为具体的实现是在状态类中取实现的。而在状态类中,也有一个changeState()方法,这个行为的作用是调用FootballTeam中的changeState()方法,来改变FootballTeam所维护的状态。

所以要理解这个交叉的类图,关键要抓住两点:

1、changeLineUp()方法在状态类中实现,而在FootballTeam类中调用;

2、changeState()方法在FootballTeam类中实现,而在状态类中调用;


状态模式有什么好处呢?为什么要这样做呢?

状态模式的本质是将条件语句的各个分支封装起来,从而实现了状态逻辑与动作的分离。当分支很多时,这种模式会给代码的维护带来很大的便利。比如说要增加一个状态,采用分支的话,就要涉及到多个分支的更改。而用状态模式,只需要增加一个新的状态实现类,在这个类中定义这个状态可以切换到哪些状态,这个状态下可以有什么行为,就可以了。当要修改一个状态,只需要修改这个状态类就可以了。

状态模式的封装性非常好,状态变化放置到类的内部来实现,外部的调用不用知道类内部如何实现状态和行为的切换。


上面例子的源代码如下:

public abstract class ScoreState {
	public abstract void changeLineUp(FootballTeam footballTeam, String score);
	
	//这个方法是所有的子类都共有的方法,所以提取到了父类中进行实现
	protected void changeState(FootballTeam footballTeam, ScoreState state){
		footballTeam.changeState(state);
	}
}
/*
 * 平局状态,有两种可能切换的状态:
 * 1、对手先进球,比分落后,这时调整阵型,状态进入比分落后状态
 * 2、己方先进球,比分领先,这时调整阵型,状态进入比分领先状态
 */
public class DrawState extends ScoreState {

	@Override
	public void changeLineUp(FootballTeam footballTeam, String score) {
		//比分落后
		if(score=="lag"){
			ScoreState lagState=new LagState();
			super.changeState(footballTeam,lagState);
			System.out.println("比分落后,阵型调整为3-4-3");
		}
		else if(score=="ahead"){
			ScoreState aheadState=new AheadState();
			super.changeState(footballTeam, aheadState);
			System.out.println("比分领先,阵型调整为5-4-1");
		}
	}

}
/*
 * 比分落后,只有一种可能切换的状态:己方进球扳平比分,比分持平,调整阵型,状态进入持平状态
 */
public class LagState extends ScoreState {

	@Override
	public void changeLineUp(FootballTeam footballTeam, String score) {
		if(score=="draw"){
			ScoreState drawState=new DrawState();
			super.changeState(footballTeam, drawState);
			System.out.println("比分持平,阵型调整为4-4-2");
		}
	}

}
/*
 * 比分领先,只有一种可能切换的状态:对手进球扳平比分,比分持平,调整阵型,状态进入持平状态
 */
public class AheadState extends ScoreState {

	@Override
	public void changeLineUp(FootballTeam footballTeam, String score) {
		if(score=="draw"){
			ScoreState drawState=new DrawState();
			super.changeState(footballTeam, drawState);
			
			System.out.println("比分持平,阵型调整为4-4-2");
		}
	}

}
public class Client {
	public static void main(String[] args) {
		
		String score=null;
		
		//定义一个球队,初始状态为持平状态
		ScoreState drawState=new DrawState();
		FootballTeam footballTeam=new FootballTeam(drawState);
		
		//比分落后
		score="lag";
		footballTeam.changeLineUp(score);
		
		//扳平比分
		score="draw";
		footballTeam.changeLineUp(score);
		
		//比分领先
		score="ahead";
		footballTeam.changeLineUp(score);
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值