被说了很多遍的设计模式---状态模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ABCD898989/article/details/53141188

[把你的理性思维慢慢变成条件反射]

本文,我们讲介绍抽象工厂模式,文章主题结构与上文一致。惯例,先来看看我们示例工程的环境:

操作系统:win7 x64

其他软件:eclipse mars,jdk7

-------------------------------------------------------------------------------------------------------------------------------------

经典问题:

状态转化。(在电商系统中,订单,物流,库存等功能中尤为常见

思路分析:

要点一:对相同的对象存在多个可以相互转化的状态。

要点二:不同状态表达不同的行为,业务含义。

示例工程:


错误写法:

创建StateChanged.java文件,具体内容如下:

package com.yonyou.iuap.gof_State;

public class StateChanged {
	public static int Condition = 0;
	public static boolean IsDone = false;

	public static void StateChanged() {
		if (Condition < 10) {
			System.out.println("Condition < 10");
		} else if (10 < Condition && Condition < 20) {
			System.out.println("10 <Condition< 20");
		} else if (20 < Condition && Condition < 30) {
			System.out.println("20 <Condition< 30");
		} else {
			if (IsDone) {
				System.out.println("Is Done");
			} else {
				System.out.println("Not Done");
			}
		}
	}
}
创建Window.java文件,具体内容如下:
package com.yonyou.iuap.gof_State;

public class Window {
	public static void main(String[] args) {
		StateChanged.Condition = 1;
		StateChanged.StateChanged();
		
		StateChanged.Condition = 12;
		StateChanged.StateChanged();
		StateChanged.Condition = 13;
		StateChanged.StateChanged();
		StateChanged.Condition = 14;
		StateChanged.StateChanged();
		StateChanged.IsDone = true;
		StateChanged.Condition = 21;
		StateChanged.StateChanged();		
	}
}

错误原因:

状态转换由“if...else...”完成,类似的实现缺点在前文中已经反复说明:过程性的代码应用在面向对象的程序中,后期会无形中增加维护与扩展性,即违反了诸多的原则。同时,对于内部成员变量,设计实现为公有的,也是一种不合适的实现。

推荐写法:


创建Condition.java文件,具体内容如下:

package com.yonyou.iuap.gof_State.two;

public class Condition {
	public int Condition = 0;
	public boolean IsDone = false;
	public State state;
	
	public Condition(){
		this.state = new ConcreteState10();
	}
	public State getState() {
		return state;
	}

	public void setState(State state) {
		this.state = state;
	}
	
	public int getCondition() {
		return Condition;
	}
	public void setCondition(int condition) {
		Condition = condition;
	}
	public boolean isIsDone() {
		return IsDone;
	}
	public void setIsDone(boolean isDone) {
		IsDone = isDone;
	}
	public void conditionChanged() {
		this.state.stateChanged(this);
	}
}
创建State.java文件,具体内容如下:

package com.yonyou.iuap.gof_State.two;

public abstract class State {
	public abstract void stateChanged(Condition context);
}
创建ConcreteState10.java,ConcreteState20.java,ConcreteState30.java,ConcreteState40.java文件,具体内容如下:

package com.yonyou.iuap.gof_State.two;

public class ConcreteState10 extends State{

	@Override
	public void stateChanged(Condition condition) {
		if(condition.getCondition()<10){
			System.out.println("Condition()<10");
		}else{
			condition.setState(new ConcreteState20());
			condition.conditionChanged();
		}
	}
}
创建ConcreteState50.java文件,具体内容如下:

package com.yonyou.iuap.gof_State.two;

public class ConcreteState50 extends State {

	@Override
	public void stateChanged(Condition condition) {
		if(condition.IsDone){
			System.out.println("Is Done");
		}else{
			System.out.println("Not Done");
		}
	}
}
创建Window.java文件,具体内容如下:
package com.yonyou.iuap.gof_State.two;

public class Window {
	public static void main(String[] args) {
		Condition condition = new Condition();
		System.out.println("Condition(1)-----------");
		condition.setCondition(1);
		condition.conditionChanged();
		System.out.println("Condition(12)----------");
		condition.setCondition(12);
		condition.conditionChanged();
		System.out.println("Condition(13)----------");
		condition.setCondition(13);
		condition.conditionChanged();
		System.out.println("Condition(14)----------");
		condition.setCondition(14);
		condition.conditionChanged();
		System.out.println("IsDone(true)-----------");
		System.out.println("Condition(21)----------");
		condition.setIsDone(true);
		condition.setCondition(21);
		condition.conditionChanged();
		System.out.println("IsDone(false)----------");
		System.out.println("Condition(22)----------");
		condition.setIsDone(false);
		condition.setCondition(22);
		condition.conditionChanged();
	}
}

推荐原因:

每一个状态都进行了职责分离,极大的方便了后续的维护性,扩展性。代码含义一目了然,减少了各个功能之间的耦合程度。

模式总结:

标准状态模式UML结构图:


状态模式:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。(主要功能是:当控制一个对象状态转换的条件表达式过于复杂是,把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。)

组成部分:Context(上下文环境类),State(抽象状态类),ConcreteState(具体状态类)三个组成部分。

模板代码:


创建Context.java文件,具体内容如下:

package com.yonyou.iuap.gof_State.one;

public class Context {
	private State state;
	
	public Context(State state){
		this.state = state;
	}

	public State getState() {
		return state;
	}

	public void setState(State state) {
		this.state = state;
		System.out.println(state.getClass().getName());
	}
	public void request(){
		state.Handle(this);
	}
}
创建State.java文件,具体内容如下:

package com.yonyou.iuap.gof_State.one;

public abstract class State {
	public abstract void Handle(Context context);
}
创建ConcreteStateA.java文件,具体内容如下:

package com.yonyou.iuap.gof_State.one;

public class ConcreteStateA extends State{

	@Override
	public void Handle(Context context) {
		context.setState(new ConcreteStateB());
	}
}
创建Window.java文件,具体内容如下:
public class Window {
	public static void main(String[] args) {
		Context c = new Context(new ConcreteStateA());
		c.request();
	}
}

反思:

首先,需要说明的是:上面的代码,我们仅仅是作为示例。在实际应用时,上下文Context类中可以扩充具有实际意义的成员变量。第二,状态需要有一个初始值,如果客户端未设定,那么程序中需要明确指明。第三,状态转化的具体实现位置:在示例中,我们是在具体状态类中实现切换,而实际上,也可以在上下文环境类中,进行统一的切换,具体时间步骤就是通过if...else...实现,当然,这种实现方法,在较少的具体子类中可以应用,并且,通过介绍该模式,这种方式也是不推荐给大家的。

应用场景:

  1. 对象的行为严格依赖于他的状态,属性等。
  2. 对象的行为存在大量与状态有关的条件判断语句。

优点:

  1. 封装了状态的转化规则,转换的位置可以在上下文类,或者,具体子类中实现。
  2. 将所有的状态变化方法归属到一个上下文类当中,方便了后续的开发与维护。
  3. 避免了大量的条件判断语句块。

缺点

  1. 如果存在大量的条件判断,应用该模式,必然会导致大量的类文件。
  2. 如果将状态转化实现在具体子类当中,可能会增加后续维护跟踪的工作量。
  3. 如果需要新增或删除,将需要修改相邻的状态对象。

-------------------------------------------------------------------------------------------------------------------------------------

至此,被说了很多遍的设计模式---状态模式 结束


参考资料:

图书:《大话设计模式》

其他博文:http://blog.csdn.NET/lovelion/article/details/7563445


猜你喜欢

转载自blog.csdn.net/ABCD898989/article/details/53141188