设计模式—–状态模式
个人博客,想要搭建个人博客的可以进来看看: http://www.ioqian.top/
状态模式 , 允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类
设计模式系列源码: https://github.com/liloqian/DesiginModeDemo
背景 , 水有三种状态,通过不同方法可以在三种状态中进行转变;我们这里要做的就是实现这个转变的过程
1.简单的实现,不是用状态模式
public class InitialDemo {
//水的三种状态
public static final int GAS = 0;
public static final int SOLID = 1;
public static final int LIQUID = 2;
//当前状态
int state = LIQUID;
//加热方法,只可以在固态执行,其他态都报error
public void warm(){
if(state == SOLID){//如果当前状态是固态就进行转变
state = GAS; //转变完成后当前状态设为气态
System.out.println("Ok : warming , solid become gas");
}else if(state == GAS){
System.out.println("Error : now is gas , what do you do!");
}else if(state == LIQUID){
System.out.println("Error : you need to become liquid to solid , them warm...");
}
}
//液化过程,只有气态执行,其他态都报error
public void liquidation(){
if(state == GAS){
state = LIQUID;
System.out.println("OK : liquindation , gas become liquid");
}else if(state == LIQUID){
System.out.println("Error : now is liquid , what do you do!");
}else if(state == SOLID){
System.out.println("Error : you need to become solid to gas ,them liquidation");
}
}
//凝固过程,只有液台可执行,其他态都报error
public void sloiding(){
if(state == LIQUID){
state = SOLID;
System.out.println("OK : Sloding , liquid become solid");
}else if (state == SOLID){
System.out.println("Error : now is Solid , what do you do!");
}else if(state == GAS){
System.out.println("Error : you need to become gas to liquid ,them Sloding");
}
}
//返回当前状态
@Override
public String toString() {
return "Now is " + ((state == GAS) ? "gas" : ((state == LIQUID) ? "liquid" : "solid"));
}
//测试
public static void main(String[] args) {
InitialDemo demo = new InitialDemo();
System.out.println(demo.toString()); //初始时液态,应该打印出液态信息
demo.sloiding();
System.out.println(demo.toString());
demo.warm();
System.out.println(demo.toString());
demo.liquidation();
System.out.println(demo.toString());
}
}
我们把所有的代码写到一块,在每个方法中通过判断当前状态是否是方法要求的,需要很多的判断语句,万一科学家发现水还有好多种混合态,哪所有的方法都要改变,我们要利用状态模式了
2.状态模式UML
- State接口,定义了一个所有具体状态的公共接口,任何状态都实现这个接口,所有状态之间可以相互替换
- Context,上下午是一个类,它拥有所有任何部状态
- ConcreteStateA , 具体状态类
3.代码
State接口
/**State接口,所有的状态(固液气)都要继承他*/
public interface State {
public void warm();
public void liquidation();
public void sloiding();
}
Context上下午
/**Context上下文*/
public class WaterContext {
//包含了所以的状态
State gasState;
State liquidState;
State soldState;
//当前状态
State currentState = null;
//在构造方法中初始化
public WaterContext(){
gasState = new Gas(this);
liquidState = new Liquid(this);
soldState = new Solid(this);
currentState = liquidState;
}
public void setCurrentState(State currentState) {
this.currentState = currentState;
}
public State getCurrentState() {
return currentState;
}
//下面上getter()用于在状态具体实现类中改变状态时得到状态
public State getGasState() {
return gasState;
}
public State getLiquidState() {
return liquidState;
}
public State getSoldState() {
return soldState;
}
}
ConcreteStateA
/**注意,每种状态不仅仅要继承State接口,还要持有一个上下午Context的引用*/
public class Gas implements State {
WaterContext waterContext ;
public Gas(WaterContext waterContext) {
this.waterContext = waterContext;
}
//错误操作
@Override
public void warm() {
System.out.println("Error : now is gas , what do you do!");
}
//正确的操作
@Override
public void liquidation() {
waterContext.setCurrentState(waterContext.getLiquidState());
System.out.println("OK : liquindation , gas become liquid");
}
//错误的操作
@Override
public void sloiding() {
System.out.println("Error : you need to become gas to liquid ,them Sloding");
}
}
/**注意,每种状态不仅仅要继承State接口,还要持有一个上下午Context的引用*/
public class Liquid implements State {
WaterContext waterContext;
public Liquid(WaterContext waterContext) {
this.waterContext = waterContext;
}
//下面2个方法都是错误的操作
@Override
public void warm() {
System.out.println("Error : you need to become liquid to solid , them warm...");
}
@Override
public void liquidation() {
System.out.println("Error : now is liquid , what do you do!");
}
//正确的操作,所有设置转变后的状态,打印ok
@Override
public void sloiding() {
waterContext.setCurrentState(waterContext.getSoldState());
System.out.println("OK : Sloding , liquid become solid");
}
}
public class Solid implements State {
WaterContext waterContext;
public Solid(WaterContext waterContext) {
this.waterContext = waterContext;
}
@Override
public void warm() {
waterContext.setCurrentState(waterContext.getGasState());
System.out.println("Ok : warming , solid become gas");
}
@Override
public void liquidation() {
System.out.println("Error : you need to become solid to gas ,them liquidation");
}
@Override
public void sloiding() {
System.out.println("Error : now is Solid , what do you do!");
}
}
测试Main
public class Main {
public static void main(String[] args) {
//正确的执行,我们在WaterContext中初始化状态为liquid
WaterContext waterContext = new WaterContext();
//liquid -> sold
waterContext.getCurrentState().sloiding();
//sold -> gas
waterContext.getCurrentState().warm();
// gas->liquid
waterContext.getCurrentState().liquidation();
}
}
//结果:
OK : Sloding , liquid become solid
Ok : warming , solid become gas
OK : liquindation , gas become liquid
Process finished with exit code 0
//错误的测试一下
WaterContext waterContext = new WaterContext();
//liquid无法执行warm,状态还是液体
waterContext.getCurrentState().warm();
//liquid -> sold
waterContext.getCurrentState().sloiding();
// 当前是sold,无法执行liquidation()操作
waterContext.getCurrentState().liquidation();
//错误测试结果和上面注释的一样
Error : you need to become liquid to solid , them warm...
OK : Sloding , liquid become solid
Error : you need to become solid to gas ,them liquidation
Process finished with exit code 0
看了代码后,结合UML类图,对状态模式更加清晰了,我们这里总结一下,在状态模式中,将一群行为封装在状态对象中,context的新闻随时可委托到它内部的任何一个状态对象,随着时间的改变,contex中的当前状态在一直改变,但是context的客户却不知道,只需要调用contex当前状态的方法就可以