java状态模式实例解析

作者: Tifkingsly | 来源:发表于2018-05-31 16:00 被阅读4次

    状态模式是一种常用的设计模式,常用于软件系统中解决多种状态下行为互异的情况。例如在音视频播放器中多种状态各自对应着不相同的处理,使用状态机可以完美实现解耦。最近在做一个项目的重构,有使用到状态模式,因此写这篇文章分享一下。

    1、状态模式概述:

    状态模式(State Pattern):允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Object for States),状态模式是一种对象行为型模式。《设计模式的艺术》

    image.png

    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)增加新的状态时会增加状态类,而且在增加新的状态类之后,环境类需要做相应的修改,不太符合开闭原则;

    结束语

    状态模式的介绍就到这,虽然状态模式在设计上能够带来很大优势。但是也不能滥用,因为对于一些简单的逻辑,随意使用状态模式会使得系统复杂度增加。如果对设计模式感兴趣的同学,推荐读一下《设计模式的艺术》这本书,写得很实用。

    相关文章

      网友评论

        本文标题:java状态模式实例解析

        本文链接:https://www.haomeiwen.com/subject/iuqqsftx.html