状态模式是一种常用的设计模式,常用于软件系统中解决多种状态下行为互异的情况。例如在音视频播放器中多种状态各自对应着不相同的处理,使用状态机可以完美实现解耦。最近在做一个项目的重构,有使用到状态模式,因此写这篇文章分享一下。
1、状态模式概述:
image.png状态模式(State Pattern):允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Object for States),状态模式是一种对象行为型模式。《设计模式的艺术》
1)Context(环境类):环境类拥有各种不同状态的对象,作为外部使用的接口,负责调用状态类接口。
2)State(抽象状态):抽象状态既可以为抽象类,也可以直接定义成接口。主要用于定义状态抽象方法,具体实现由子类负责。
3)ConcreteState(具体状态类):具体状态类为抽象状态的实现者,不同的状态类对应这不同的状态,其内部实现也不相同。环境类中使用不同状态的对象时,能实现不同的处理逻辑。
2、状态模式示例:
示例为真实项目,一个即时通讯客户端连接服务端网络的设计。客户端连接服务器时存在多种状态,最初是通过if-else判断来实现,代码耦合度比较高。使用状态设计模式之后,代码清晰很多,耦合降低。类图与上面的基本一样,因此此处不再展示,直接上代码。
public interface ConnectState {
void handleRequest();
}
public class InitState implements ConnectState{
private ConnectMachine connectMachine;
private boolean connectResult;
public InitState(ConnectMachine connectMachine) {
this.connectMachine = connectMachine;
}
@Override
public void handleRequest() {
doConnect();
connectMachine.waitingConnect();
}
private void doConnect() {
//connect server
if (connectResult) {
connectSuccess();
} else {
connectFailure();
}
}
private void connectSuccess() {
connectMachine.connectSuccess();
}
private void connectFailure() {
connectMachine.connectFailure();
}
}
public class ConnectingState implements ConnectState{
private ConnectMachine connectMachine;
public ConnectingState(ConnectMachine connectMachine) {
this.connectMachine = connectMachine;
}
@Override
public void handleRequest() {
waitingConnect();
}
private void waitingConnect() {
//loading and do something
}
}
public class ConnectSuccessState implements ConnectState{
private ConnectMachine connectMachine;
public ConnectSuccessState(ConnectMachine connectMachine) {
this.connectMachine = connectMachine;
}
@Override
public void handleRequest() {
connectSuccess();
}
private void connectSuccess() {
//do something
}
}
public class ConnectFailureState implements ConnectState{
private ConnectMachine connectMachine;
public ConnectFailureState(ConnectMachine connectMachine) {
this.connectMachine = connectMachine;
}
@Override
public void handleRequest() {
connectFailure();
}
private void connectFailure() {
//do something
}
}
public class ReConnectingState implements ConnectState{
private ConnectMachine connectMachine;
public ReConnectingState(ConnectMachine connectMachine) {
this.connectMachine = connectMachine;
}
@Override
public void handleRequest() {
reConnect();
}
private void reConnect() {
//disconnect old connect and connect again
connectMachine.disConnect();
connectMachine.doConnect();
}
}
public class DisconnectState implements ConnectState {
private ConnectMachine connectMachine;
public DisconnectState(ConnectMachine connectMachine) {
this.connectMachine = connectMachine;
}
@Override
public void handleRequest() {
disConnect();
}
private void disConnect() {
//do something
}
}
public class ConnectMachine {
private ConnectState initState;
private ConnectState connectingState;
private ConnectState reconnectState;
private ConnectState disConnectState;
private ConnectState connectSuccessState;
private ConnectState connectFailureState;
public ConnectMachine() {
initState = new InitState(this);
connectingState = new ConnectingState(this);
reconnectState = new ReConnectingState(this);
disConnectState = new DisconnectState(this);
connectSuccessState = new ConnectSuccessState(this);
connectFailureState = new ConnectFailureState(this);
}
public void doConnect() {
initState.handleRequest();
}
public void waitingConnect() {
connectingState.handleRequest();
}
public void reConnect() {
reconnectState.handleRequest();
}
public void disConnect() {
disConnectState.handleRequest();
}
public void connectSuccess() {
connectSuccessState.handleRequest();
}
public void connectFailure() {
connectFailureState.handleRequest();
}
}
如果不使用状态模式,所有的逻辑判断全部写在ConnectMachine类里面,而且是通过大量if-else判断实现,代码可读性比较差。改成状态模式之后,实现细节交给具体状态类去实现,ConnectMachine只是提供给外部系统使用的接口,具体实现对于用户来说是不可的。因为只是展示状态模式的设计,使用的是回调的方式,在项目中使用时可以引入Rxjava,响应式编程更加能体会到其中妙处。
3、状态模式优缺点分析:
优点:
1)面向接口式编程,将实现细节巧妙封装在各个不同的状态类中,状态转换交给状态类自己去实现,外部无需关心;
2)将由大量业务、大量逻辑判断的代码去除,状态类内部通过状态的转换实现相关逻辑,代码可读性更好;
缺点:
1)增加新的状态时会增加状态类,而且在增加新的状态类之后,环境类需要做相应的修改,不太符合开闭原则;
结束语
状态模式的介绍就到这,虽然状态模式在设计上能够带来很大优势。但是也不能滥用,因为对于一些简单的逻辑,随意使用状态模式会使得系统复杂度增加。如果对设计模式感兴趣的同学,推荐读一下《设计模式的艺术》这本书,写得很实用。
网友评论