状态模式
状态模式:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。
那么为什么必须要状态模式,不用状态模式可以吗?当然可以,但是还是回到了代码的可维护性、可扩展性、可复用性这个层面上来考虑问题。比如一个车,不同的档位下转速、车速等是不一样的,当然我们可以在每个方法中判断当前档位来控制车的状态,但是档位越来越多的时候呢,我们就会在每个方法嵌套大量的ifelse,这无疑是非常糟糕的代码,可读性非常的差,并且如果需求发生了改变,我们很难去修改代码(很容易出现错误),但是如果我们考虑将这些状态都作为一个类,在每一个类内部进行处理、判断和相应的切换,这样思路就非常的清晰,如果再增加一种状态,代码需要修改的地方会非常的少,对于状态非常多的情景来说非常的方便。
状态模式比较容易理解,类图也比较简单
下面就车换挡的例子做一个demo
package state; public interface State { void speed(); void rotateSpeed(); }
package state; public class FristGear implements State{ @Override public void speed() { System.out.println("速度10"); } @Override public void rotateSpeed() { System.out.println("转速10"); } }
package state; public class SecondGear implements State { @Override public void speed() { System.out.println("速度20"); } @Override public void rotateSpeed() { System.out.println("转速20"); } }
package state; public class ThridGear implements State { @Override public void speed() { System.out.println("速度30"); } @Override public void rotateSpeed() { System.out.println("转速30"); } }
package state; public class Car { public static final State fristGear = new FristGear(); public static final State secondGear = new SecondGear(); public static final State thirdGear = new ThridGear(); private State state = fristGear; public void setState(State state) { this.state = state; } public void carState() { System.out.println("当前车状态:"); state.speed(); state.rotateSpeed(); } }
package state; public class Client { public static void main(String[] args) { Car car = new Car(); car.carState(); car.setState(Car.secondGear); car.carState(); car.setState(Car.thirdGear); car.carState(); } }
状态模式的优点
1、每个状态的行为局部化到它自己的类中
2、将容易产生问题的if else结构去掉,使得代码的可维护性更强,不易出错。
3、使用多态代替了条件判断,这样我们代码的扩展性更强,当要增加一些状态时,会非常的容易。
4、让每一个状态对修改关闭,对扩展开放
5、状态是可以被共享的,这个在上面的例子当中有体现,看下Car类当中的几个static final变量就知道了,因为状态类一般是没有自己的内部状态的,所有它只是一个具有行为的对象,因此是可以被共享的。
6、状态的转换更加简单安全,简单体现在状态的分割,因为我们把一堆if else分割成了若干个代码段分别放在几个具体的状态类当中,所以转换起来当然更简单,而且每次转换的时候我们只需要关注一个固定的状态到其他状态的转换。安全体现在类型安全,我们设置状态时,必须是状态接口的实现类,这可以杜绝数不正确的状态码。
相信大家在学习状态模式ai时候都会有一个疑问:状态模式和策略模式有什么区别。在这里说下我的理解,两者在类图和结构基本一样,不同的是使用场景的侧重点,状态模式更强调的是随着外部条件的变化,状态对象内部的方法做出不同的动作;策略模式侧重的是根据外部条件选取一个合适的策略来执行动作,并做出的对应的响应。策略模式中我们的策略类通常只有一个方法,而我们的状态类一般则可能有多个方法,来更全面的展示状态对象。