关闭

设计模式读书笔记-----状态模式

110人阅读 评论(0) 收藏 举报
分类:
   在介绍状态模式之前,我们先来看这样一个实例:你公司力排万难终于获得某个酒店的系统开发项目,并且最终落到了你的头上。下图是他们系统的主要工作(够简单)。


       当你第一眼看到这个系统的时候你就看出来了这是一个状态图,每个框框都代表了房间的状态,箭头表示房间状态的转换。分析如下:房间有三个状态:空闲、已预订、已入住,状态与状态之间可以根据客户的动作来进行转换。定义每个状态的值。

    public static final int FREEMTIME_STATE = 0;  //空闲状态  
        public static final int BOOKED_STATE = 1;     //已预订状态  
        public static final int CHECKIN_STATE = 2;    //入住状态  
          
          
        int state = FREEMTIME_STATE;     //初始状态  

   通过客户的动作将每个状态整合起来,对于这个“最简单”的方式肯定是if…else if…else啦!所以这里我们就通过动作将所有的状态全面整合起来。分析得这里有四个动作:预订、入住、退订、退房。如下:

    /** 
         * @desc 预订 
         * @return void 
         */  
        public void bookRoom(){  
            if(state == FREEMTIME_STATE){   //空闲可预订  
                if(count > 0){  
                    System.out.println("空闲房间,完成预订...");  
                    state =  BOOKED_STATE;     //改变状态:已预订  
                    count --;  
                    //房间预订完了,提示客户没有房源了  
                    if(count == 0){  
                        System.out.println("不好意思,房间已经预订完,欢迎您下次光临...");  
                    }  
                }  
                else{  
                    System.out.println("不好意思,已经没有房间了....");  
                }  
            }  
            else if(state == BOOKED_STATE){  
                System.out.println("该房间已经被预订了...");  
            }  
            else if(state == CHECKIN_STATE){  
                System.out.println("该房间已经有人入住了...");  
            }  
        }  
          
        /** 
         * @desc 入住 
         * @return void 
         */  
        public void checkInRoom(){  
            if(state == FREEMTIME_STATE){  
                if(count > 0){  
                    System.out.println("空闲房间,入住...");  
                    state =  CHECKIN_STATE;     //改变状态:已预订  
                    count --;  
                    //房间预订完了,提示客户没有房源了  
                    if(count == 0){  
                        System.out.println("不好意思,房间已经预订完,欢迎您下次光临...");  
                    }  
                }  
                else{  
                    System.out.println("不好意思,已经没有房间了....");  
                }  
                  
            }  
            else if(state == BOOKED_STATE){  
                if("如果该房间是您预订的"){  
                    System.out.println("入住....");  
                    state = CHECKIN_STATE;  
                }  
                else{  
                    System.out.println("您没有预订该房间,请先预订...");  
                }  
            }  
            else if(state == CHECKIN_STATE){  
                System.out.println("该房间已经入住了...");  
            }  
        }  
          
        /** 
         * @desc 退订 
         * @return void 
         */  
        public void unsubscribeRoom(){  
            if(state == FREEMTIME_STATE){  
            }  
            else if(state == CHECKIN_STATE){  
                  
            }  
            else if(state == BOOKED_STATE){  
                System.out.println("已退订房间...");  
                state = FREEMTIME_STATE;  
                count ++;  
            }  
        }  
          
        /** 
         * @desc 退房 
         * @return void 
         */  
        public void checkOutRoom(){  
            if(state == FREEMTIME_STATE){  
                  
            }  
            else if(state == BOOKED_STATE){  
                  
            }  
            else if(state == CHECKIN_STATE){  
                System.out.println("已退房..");  
                state = FREEMTIME_STATE;  
                count++;  
            }  
        }  

 对于上面的代码你是否满意呢?满意那么你就没有必要往下看了,不满意我们接着讲。

       正当你完成这个“复杂”if..else if …else时(我都写了一会儿),你客户说,我们需要将某些房间保留下来以作为备用(standbyState),于是你发现你悲剧了,因为你发现你要在所有的操作里都要判断该房间是否为备用房间。当你老大经过你身边的时候发现你正在纠结怎么改的时候,你老大就问你为什么不换一个角度思考以状态为原子来改变它的行为,而不是通过行为来改变状态呢?于是你就学到了状态模式。

一、模式定义

       在很多情况下,一个对象的行为取决于它的一个或多个变化的属性,这些属性我们称之为状态,这个对象称之为状态对象。对于状态对象而已,它的行为依赖于它的状态,比如你要预订房间,那么只有当该房间为空闲时你才能预订,你想入住该房间也只有当你预订了该房间或者该房间为空闲时。对于这样的一个对象,当它在于外部事件产生互动的时候,其内部状态就会发生改变,从而使得他的行为也随之发生改变。

       那么何为状态模式呢?所谓状态模式就是允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。

二、模式结构

       下图为状态模式的UML图。


       状态模式包含如下角色:
       Context: 环境类。可以包括一些内部状态。
       State: 抽象状态类。State定义了一个所有具体状态的共同接口,任何状态都实现这个相同的接口,这样一来,状态之间就可以互相转换了。
       ConcreteState: 具体状态类。具体状态类,用于处理来自Context的请求,每一个ConcreteState都提供了它对自己请求的实现,所以,当Context改变状态时行为也会跟着改变。

  三、模式实现

       依然是上面那个酒店的实例。对于该实例的UML图如下:


       首先是状态接口:State

    public interface State {  
        /**  
         * @desc 预订房间  
         * @return void  
         */  
        public void bookRoom();  
          
        /**  
         * @desc 退订房间  
         * @return void  
         */  
        public void unsubscribeRoom();  
          
        /**  
         * @desc 入住  
         * @return void  
         */  
        public void checkInRoom();  
          
        /**  
         * @desc 退房  
         * @return void  
         */  
        public void checkOutRoom();  
          
    }  
           然后是房间类  
    public class Room {  
        /*  
         * 房间的三个状态  
         */  
        State freeTimeState;    //空闲状态  
        State checkInState;     //入住状态  
        State bookedState;      //预订状态  
      
        State state ;    
          
        public Room(){  
            freeTimeState = new FreeTimeState(this);  
            checkInState = new CheckInState(this);  
            bookedState = new BookedState(this);  
              
            state = freeTimeState ;  //初始状态为空闲  
        }  
          
        /**  
         * @desc 预订房间  
         * @return void  
         */  
        public void bookRoom(){  
            state.bookRoom();  
        }  
          
        /**  
         * @desc 退订房间  
         * @return void  
         */  
        public void unsubscribeRoom(){  
            state.unsubscribeRoom();  
        }  
          
        /**  
         * @desc 入住  
         * @return void  
         */  
        public void checkInRoom(){  
            state.checkInRoom();  
        }  
          
        /**  
         * @desc 退房  
         * @return void  
         */  
        public void checkOutRoom(){  
            state.checkOutRoom();  
        }  
      
        public String toString(){  
            return "该房间的状态是:"+getState().getClass().getName();  
        }  
          
        /*  
         * getter和setter方法  
         */  
          
        public State getFreeTimeState() {  
            return freeTimeState;  
        }  
      
        public void setFreeTimeState(State freeTimeState) {  
            this.freeTimeState = freeTimeState;  
        }  
      
        public State getCheckInState() {  
            return checkInState;  
        }  
      
        public void setCheckInState(State checkInState) {  
            this.checkInState = checkInState;  
        }  
      
        public State getBookedState() {  
            return bookedState;  
        }  
      
        public void setBookedState(State bookedState) {  
            this.bookedState = bookedState;  
        }  
      
        public State getState() {  
            return state;  
        }  
      
        public void setState(State state) {  
            this.state = state;  
        }  
      
    }  

     然后是3个状态类,这个三个状态分别对于这:空闲、预订、入住。其中空闲可以完成预订和入住两个动作,预订可以完成入住和退订两个动作,入住可以退房。

    /**  
     * @project: design_state  
     * @author chenssy 
     * @date 2013-8-24  
     * @Description: 空闲状态只能预订和入住 
     */  
    public class FreeTimeState implements State {  
          
        Room hotelManagement;  
          
        public FreeTimeState(Room hotelManagement){  
            this.hotelManagement = hotelManagement;  
        }  
          
          
        public void bookRoom() {  
            System.out.println("您已经成功预订了...");  
            hotelManagement.setState(hotelManagement.getBookedState());   //状态变成已经预订  
        }  
      
        public void checkInRoom() {  
            System.out.println("您已经成功入住了...");  
            hotelManagement.setState(hotelManagement.getCheckInState());   //状态变成已经入住  
        }  
      
        public void checkOutRoom() {  
            //不需要做操作  
        }  
      
        public void unsubscribeRoom() {  
            //不需要做操作  
        }  
      
    }  

[java] view plain copy

    /**  
     * @project: design_state  
     * @author chenssy 
     * @date 2013-8-24  
     * @Description: 入住状态房间只能退房 
     */  
    public class BookedState implements State {  
        Room hotelManagement;  
          
        public BookedState(Room hotelManagement) {  
            this.hotelManagement = hotelManagement;  
        }  
      
        public void bookRoom() {  
            System.out.println("该房间已近给预定了...");  
        }  
      
        public void checkInRoom() {  
            System.out.println("入住成功...");   
            hotelManagement.setState(hotelManagement.getCheckInState());         //状态变成入住  
        }  
      
        public void checkOutRoom() {  
            //不需要做操作  
        }  
      
        public void unsubscribeRoom() {  
            System.out.println("退订成功,欢迎下次光临...");  
            hotelManagement.setState(hotelManagement.getFreeTimeState());   //变成空闲状态  
        }  
      
    }  


[java] view plain copy

    /**  
     * @project: design_state  
     * @author chenssy 
     * @date 2013-8-24  
     * @Description: 入住可以退房 
     */  
    public class CheckInState implements State {  
        Room hotelManagement;  
        public CheckInState(Room hotelManagement) {  
            this.hotelManagement = hotelManagement;  
        }  
      
        public void bookRoom() {  
            System.out.println("该房间已经入住了...");  
        }  
      
        public void checkInRoom() {  
            System.out.println("该房间已经入住了...");  
        }  
      
        public void checkOutRoom() {  
            System.out.println("退房成功....");  
            hotelManagement.setState(hotelManagement.getFreeTimeState());     //状态变成空闲  
        }  
      
        public void unsubscribeRoom() {  
            //不需要做操作  
        }  
      
    }  


      最后是测试类

[java] view plain copy

    public class Test {  
        public static void main(String[] args) {  
            //有3间房  
            Room[] rooms = new Room[2];  
            //初始化  
            for(int i = 0 ; i < rooms.length ; i++){  
                rooms[i] = new Room();  
            }  
            //第一间房  
            rooms[0].bookRoom();    //预订  
            rooms[0].checkInRoom();   //入住  
            rooms[0].bookRoom();    //预订  
            System.out.println(rooms[0]);  
            System.out.println("---------------------------");  
              
            //第二间房  
            rooms[1].checkInRoom();  
            rooms[1].bookRoom();  
            rooms[1].checkOutRoom();  
            rooms[1].bookRoom();  
            System.out.println(rooms[1]);  
        }  
      
    }  
运行结果



       四、模式优缺点

       优点

       1、封装了转换规则。
       2、枚举可能的状态,在枚举状态之前需要确定状态种类。
       3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
       4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
       5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

       缺点

       1、状态模式的使用必然会增加系统类和对象的个数。
       2、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
       3、状态模式对“开闭原则”的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。

       五、模式适用场景

1、对象的行为依赖于它的状态(属性)并且可以根据它的状态改变而改变它的相关行为。
2、代码中包含大量与对象状态有关的条件语句

       六、模式总结

       1、状态模式允许一个对象基于内部状态而拥有不同的行为。

       2、Context会将行为委托给当前状态对象。

       3、状态模式对“开闭原则”支持不是很好。



0
0
查看评论

C++设计模式之状态模式(二)

2、智能空调的设计与实现 某软件公司将开发一套智能空调系统: 系统检测到温度处于20---30度之间,则切换到常温状态;温度处于30---45度,则切换到制冷状态; 温度小于20度,则切换到制热状态。请使用状态模式对此系统进行设计。    ...
  • ApeLife
  • ApeLife
  • 2014-08-30 22:14
  • 1364

4.php设计模式:状态模式的使用场景

在这儿给大家说点事儿。我的博客搬家到github主页上了。我的博客。以后首发都在github上了。csdn也会继续更新。可能就是稍微慢一下。另外最近搞了一个支付的开源项目。这是项目地址 目前已经支持: * 支付宝的 即时到帐、移动支付、加密退款接口。 * 微信的目前已经支持:app支付、扫码支...
  • hel12he
  • hel12he
  • 2016-06-30 09:16
  • 804

Java设计模式之状态模式

本文属于"23种设计模式"系列,介绍状态模式。
  • jason0539
  • jason0539
  • 2015-04-14 07:54
  • 14489

PHP设计模式系列(十一):状态模式

状态模式状态模式(State Pattern) :允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects for States),状态模式是一种对象行为型模式。模式结构状态模式包含如下角色: Context: 环境类 State: 抽象状态类 Con...
  • qq_32300363
  • qq_32300363
  • 2017-04-30 16:28
  • 377

实用设计模式之状态模式

状态模式的针对性很强,当有状态变化的时候很多工程师会倾向于选择状态模式,但在使用时仍然存在着很多问题,比如状态的拆分不清晰、状态的变迁不准确、类的职责划分不单一等,一旦与具体的业务逻辑和已有的代码上下文放在一起,就出现了混乱。因此,本文以一个实际的例子来总结一下在现实当中如何使用状态模式。 ...
  • caowenbin
  • caowenbin
  • 2013-03-17 16:29
  • 3562

C语言和设计模式(状态模式)

【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】     状态模式是协议交互中使用得比较多的模式。比如说,在不同的协议中,都会存在启动、保持、中止等基本状态。那么怎么灵活地转变这些状态就是我们需要考虑的事情。...
  • feixiaoxing
  • feixiaoxing
  • 2012-01-08 20:58
  • 8993

设计模式之状态STATE模式(C++)

状态模式:属于行为型模式的其中一种,其允许一个对象在内部改变状态时改变它的行为,对象看起来似乎修改了它的类。 状态模式主要解决的是当控制一个对象的状态转换条件表达式过于复杂时的情况,把状态的逻辑判断转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。好处就是讲于特定状态相关的行为局部化,并且...
  • hailong0715
  • hailong0715
  • 2016-07-22 14:46
  • 615

【设计模式】---状态模式详解及应用实例

近期在机房合作开发中,对状态模式又有了进一步的理解,下面就以机房收费系统为例子来学习装套模式    1. 状态模式基本概念 状态模式(State Pattern)是设计模式的一种,属于行为模式。 定义(源于Design Pattern):当一个对象的内在状态改变...
  • yudandan10
  • yudandan10
  • 2013-08-26 17:41
  • 4245

设计模式读书笔记-----状态模式

在介绍状态模式之前,我们先来看这样一个实例:你公司力排万难终于获得某个酒店的系统开发项目,并且最终落到了你的头上。下图是他们系统的主要工作(够简单)。        当你第一眼看到这个系统的时候你就看出来了这是一个状态图,每个框框都代表了房间的状态,...
  • chenssy
  • chenssy
  • 2013-09-04 21:19
  • 12100

你还在用if else吗?——状态模式、职责链模式

小时候写日记都是这么写的:上午七点起床,八点之前洗脸刷牙吃早饭,十二点之前好好上课,中午一点,吃午饭,下午两点到六点,上课,下课,找请假,明天妈妈要带我去姥姥家,九点之前,看动画片,九点钟,收拾去姥姥家的东西,十点以后,睡觉。 我们把请假这块在充实一下:找班长请假,班长只能请半天,否则班长向老师申...
  • laner0515
  • laner0515
  • 2012-03-22 20:02
  • 21802
    个人资料
    • 访问:348846次
    • 积分:3674
    • 等级:
    • 排名:第10493名
    • 原创:83篇
    • 转载:116篇
    • 译文:0篇
    • 评论:61条
    博客专栏
    说明
    Android 交流学习群 QQ:458506426