一、背景

   最近系统的学习一下Java设计模式,下了2本电子书,《设计模式之禅》与《Head First 设计模式》,支持国产嘛,先看《设计模式之禅》,首先说一下对它的感觉,叙述比较简洁明了,举例很有趣味性、贴切,吸引人,有很多对比的例子(不采用设计模式和采用设计模式),对初学者来说还不错。有一个小遗憾就是:作者所画的类图有时并没有和代码对应。今天看到状态模式了,突然想来记录点什么,所以这篇博文就诞生了。


二、状态分析

还是拿作者的例子——电梯,电梯有四种动作:开门,关门,运行,停止。对应四种状态:门敞状态,门闭状态,运行状态,停止状态,它们之间的关系如下:


开门(open) 关门(close) 运行(run) 停止(stop)
门敞状态 no ok no no
门闭状态 ok no ok ok
运行状态 no no no ok
停止状态 ok no ok no


三、画出类图

才刚开始学画类图了,采用的工具是starUML,如下:

Java设计模式之状态模式_第1张图片


四、代码

在类图基础上,利用starUML自动生成代码,然后再修改而成了。

   1、环境封装类Context

public class Context {
    private LiftState liftState;
    public LiftState getLiftState() {
        return this.liftState;
    }
                                                                                                                                                                                                    
    public void setListState(LiftState liftState) {
        liftState.setContext(this);
        this.liftState = liftState;
    }
                                                                                                                                                                                                    
    public void open() {
        this.liftState.open();
    }
                                                                                                                                                                                                    
    public void close() {
        this.liftState.close();
    }
                                                                                                                                                                                                    
    public void run() {
        this.liftState.run();
    }
                                                                                                                                                                                                    
    public void stop() {
        this.liftState.stop();
    }
}


   2、状态抽象类LiftState

public abstract class LiftState {
    protected Context context;
    public void setContext(Context _context) {
        this.context = _context;
    }
                                                                                                                                                                          
    public abstract void open();
                                                                                                                                                                          
    public abstract void close();
                                                                                                                                                                          
    public abstract void run();
                                                                                                                                                                          
    public abstract void stop();
}


   3、四种状态类和状态池类OpenningState,ClosingState,RunningState,StoppingState,StatesPools

       (1)OpenningState


public class OpenningState extends LiftState {
    public void open() {
        //已经打开了,不做任何操作
    }
                                                                                                                                                  
    public void close() {
        //打开状态,是可以关闭的
        System.out.println("关闭电梯...");
        super.context.setListState(StatesPool.closingState);
    }
                                                                                                                                                  
    public void run() {
        //开的时候,当然是不能跑的
    }
                                                                                                                                                  
    public void stop() {
        //开的时候,也没必要停
    }
}


       (2)ClosingState

public class ClosingState extends LiftState {
    public void open() {
        //关闭了当然是可以打开的
        System.out.println("电梯打开");
        super.context.setListState(StatesPool.openningState);
    }
                                                                                                                                        
    public void close() {
        //已经关闭了
                                                                                                                                        
    }
                                                                                                                                        
    public void run() {
        //关闭当然是可以运行的
        System.out.println("电梯运行");
        super.context.setListState(StatesPool.runningState);
    }
                                                                                                                                        
    public void stop() {
        //关闭也可以停止的
        System.out.println("电梯停止");
        super.context.setListState(StatesPool.stoppingState);
    }
}

       (3)RunningState

public class RunningState extends LiftState {
    public void open() {
        //正在运行的时候不能开
    }
                                                                                                                            
    public void close() {
        //正在运行的时候不能关
    }
                                                                                                                            
    public void run() {
        //已经在运行了
    }
                                                                                                                            
    public void stop() {
        //运行时候,当然是可以停的
        System.out.println("停止电梯...");
        // 改变状态
        super.context.setListState(StatesPool.stoppingState);
    }
}


       (4)StoppingState

public class StoppingState extends LiftState {
    public void open() {
        //停止状态下可以打开啦
        System.out.println("电梯打开");
        super.context.setListState(StatesPool.openningState);
    }
                                                                                                                 
    public void close() {
                                                                                                                 
    }
                                                                                                                 
    public void run() {
        //停止状态下可以继续运行了
        System.out.println("电梯运行");
        super.context.setListState(StatesPool.runningState);
    }
                                                                                                                 
    public void stop() {
                                                                                                                 
    }
}


       (5)StatesPools

public class StatesPool {
    public static final OpenningState openningState = new OpenningState();
    public static final ClosingState closingState = new ClosingState();
    public static final RunningState runningState = new RunningState();
    public static final StoppingState stoppingState = new StoppingState();
}

   4、客户端调用类Client


public class Client {
                                                                            
    public static void main(String[] args) {
        Context context = new Context();
        context.setListState(new ClosingState());
                                                                                
        context.open();
        context.close();
        context.run();
        context.stop();
        context.open();
                                                                                
    }
}

   5、运行结果


电梯打开
关闭电梯...
电梯运行
停止电梯...
电梯打开


五、总结

行为与状态有对应关系,状态的切换伴随着相应的行为,都可以用状态模式了。另外抱怨51cto一句:再做好一点行不行啊,每次贴代码都要我重新选择语言,上面贴的代码都选了n次Java了,就不能帮我记住吗?

ps:代码地址http://down.51cto.com/data/1029676