设计模式之状态模式

一、定义

允许一个对象内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
意思是一个对象可能有多重状态,我们平时都是用if-else来分开状态,根据不同的状态来调用不同的行为方法。

二、举例说明

               我个人不喜欢玩其他的游戏,就喜欢玩Dota。那我就用dota中的杀人称号来举例说明。事先声明,在这里我说的都是短期内杀人,当你杀死第一个人的时候是First Blood,第二个人是Double Kill,三个人是Triple Kill,杀人数达到8个  M-m-m-m…Monster Kill ,杀人数达到9个 Godlike ,杀人数达到10个 Holy Shit。中间的大于3个且小于8个的不多说了,为了少弄几个类,就叫牛逼吧。

               如果让我们编程的话,没有学过设计模式的同学可能会这样来写程序。

             

public String KillName(int killCount){
		String killName = null;
		if(killCount==1){
			killName = "First Blood";
		}else if(killCount==2){
			killName = "Double Kill";
		}
		else if(killCount==3){
			killName = "Triple Kill";
		}
		else if(killCount>3 && killCount<8){
			killName = "牛逼";
		}
		else if(killCount==8){
			killName = "M-m-m-m…Monster Kill";
		}
		else if(killCount==9){
			killName = "Godlike";
		}
		else if(killCount==10){
			killName = "Holy Shit";
		}
		return killName;
	}

问题是什么呢?

1、如果killCount有1000种叫法,那么就得写1000个if

2、如果每种状态处理的业务比较多的话,就会造成类非常的庞大

2、如果有新的状态的话,我们还得继续添加if-else。

为了解决这些问题我们可以采用状态模式。

状态模式的类图:


三、代码说明

KillNameManager类 上下文

public class KillNameManager {
	
	private Map<String,Integer> mapKillCount = new HashMap<String, Integer>();
	private Map<String,KillState> mapKillState = new HashMap<String, KillState>();
	
	public Map<String, Integer> getMapKillCount() {
		return mapKillCount;
	}


	public void setMapKillCount(Map<String, Integer> mapKillCount) {
		this.mapKillCount = mapKillCount;
	}


	public Map<String, KillState> getMapKillState() {
		return mapKillState;
	}


	public void setMapKillState(Map<String, KillState> mapKillState) {
		this.mapKillState = mapKillState;
	}


	public String killPeople(String player){
		Integer killCount = mapKillCount.get(player);
		if(null == killCount){
			killCount = 0;
		}
		
		killCount++;
		mapKillCount.put(player, killCount);
		
		KillState killState = mapKillState.get(player);
		if(killState==null){
			killState = new KillFirstPeopleState();
			mapKillState.put(player, killState);
		}
		return  killState.killPeople(player, this);
	}
	//1、把不同的处理业务封装在不同的状态中,这样Manager上下文的类就简化了,不会变的庞大
	//2、把逻辑业务放在状态中了,这样我们就可以继续扩展下去。
	//3、我们不用修改Manager中的代码,只要实现KillState继续写状态就行
	/*public String KillName(int killCount){
		String killName = null;
		if(killCount==1){
			killName = "First Blood";
		}else if(killCount==2){
			killName = "Double Kill";
		}
		else if(killCount==3){
			killName = "Triple Kill";
		}
		else if(killCount>3 && killCount<8){
			killName = "牛逼";
		}
		else if(killCount==8){
			killName = "M-m-m-m…Monster Kill";
		}
		else if(killCount==9){
			killName = "Godlike";
		}
		else if(killCount==10){
			killName = "Holy Shit";
		}
		return killName;
	}*/
}

状态接口:

public interface KillState {
	String killPeople(String player,KillNameManager nameManager);
}

Client 类

public class Player {
	
	private static String playerName = "小吕布";
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		KillNameManager nameManager = new KillNameManager();
		for(int i=0;i<10;i++){
			String killName = nameManager.killPeople(playerName);
			System.out.println(killName);
		}

	}

}

具体的状态类:

public class KillFirstPeopleState implements KillState {

	@Override
	public String killPeople(String player, KillNameManager nameManager) {
		String killName = "First Blood";
		if(nameManager.getMapKillCount().get(player)>0){
			nameManager.getMapKillState().put(player, new KillSecondPeopleState());
		}
		return killName;
	}

}

public class KillSecondPeopleState implements KillState {

	@Override
	public String killPeople(String player, KillNameManager nameManager) {
		String killName = "Double Kill";
		if(nameManager.getMapKillCount().get(player)>=2){
			nameManager.getMapKillState().put(player, new KillThreePeopleState());
		}
		return killName;
	}

}

public class KillThreePeopleState implements KillState {

	@Override
	public String killPeople(String player, KillNameManager nameManager) {
		String killName = "Triple Kill";
		if(nameManager.getMapKillCount().get(player)>=3 && nameManager.getMapKillCount().get(player)<8){
			nameManager.getMapKillState().put(player, new KillLotofState());
		}
		return killName;
	}

}

public class KillLotofState implements KillState {

	@Override
	public String killPeople(String player, KillNameManager nameManager) {
		String killName = "牛逼";
		if(nameManager.getMapKillCount().get(player)==8){
			nameManager.getMapKillState().put(player, new KillEightPeopleState());
		}
		return killName;
	}

}

public class KillEightPeopleState implements KillState {

	@Override
	public String killPeople(String player, KillNameManager nameManager) {
		String killName = "M-m-m-m…Monster Kill";
		if(nameManager.getMapKillCount().get(player)>=8){
			nameManager.getMapKillState().put(player, new KillNinePeopleState());
		}
		return killName;
	}

}

public class KillNinePeopleState implements KillState {

	@Override
	public String killPeople(String player, KillNameManager nameManager) {
		String killName = "Godlike";
		if(nameManager.getMapKillCount().get(player)>=9){
			nameManager.getMapKillState().put(player, new KillTenPeopleState());
		}
		return killName;
	}

}

public class KillTenPeopleState implements KillState {

	@Override
	public String killPeople(String player, KillNameManager nameManager) {
		String killName = "Holy Shit";
		
		return killName;
	}

}

运行结果:



这个例子的类图是:

前面的状态对后面的状态有依赖关系。


四、总结


1、状态模式的优缺点

         优点:

              简化应用逻辑控制:状态模式使用单独的类来封装一个状态的处理。如果把一个大的程序控制分成很多小块,每块定义一个状态来代表,那么就可以把这些逻辑控制的代码分散到很多单独的状态类中去,这样就把着眼从执行状态提高到整个对象的状态,使得代码结构和意图更清晰,从而简化应用的逻辑控制。

              更好的分离状态和行为:状态模式通过设置所有状态类的公共接口,把状态和状态对应的行为分离开,把所有与一个特定的状态相关的行为都放入一个对象中,使得应用程序在控制的时候,只需要关心状态的切换,而不用关心这个状态对应的真正处理。

              更好的扩展性:引入了状态处理的公共接口后,使得扩展新的状态变的非常的容易,只需要增加一个实现状态处理的公共接口的实现类,然后在运行状态维护的地方,设置状态变化到这个新的状态即可。

          缺点:

              就是每一个状态对应一个状态类,这样会导致有众多的状态类,会使得程序变的混乱。

2、状态模式的本质

           根据状态来分离和选择行为

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值