注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

东东的博客

江南烟雨,同大家一起分享

 
 
 

日志

 
 

设计模式读书笔记之状态模式(State Pattern)  

2010-07-13 19:54:25|  分类: 设计模式相关 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

状态模式:当对象内部状态发生变化时允许改变其行为,使对象看起来像自身发生了变化一样。

状态模式解决的问题是当对象的状态转换的条件过于复杂的情况, 它把状态的判断逻辑以及状态发生变化后对象的行为改变转移到不同的状态对象中去。

比如: 一个人Person, 他在不同的时间, 自身处在不同的状态, 从而有不同的行为.于是我们通常会写出这样的代码:


view plaincopy to clipboardprint?
public class Person {  
    public void doSomething(int time){  
        if(time>8&&time<=9){  
            System.out.println("I am on bus, suffering...");  
        }  
        else if(time>9&&time<=12){  
            System.out.println("I am working.");  
        }  
        else if(time>12&&time<=13){  
            System.out.println("I am having lunch.");  
        }  
        else if(time>13&&time<=18){  
            System.out.println("I am working.");  
        }  
        else if(time>18&&time<=23){  
            System.out.println("Oh yeah, going home.");  
        }  
        else{  
            System.out.println("Zzz Zzz Zzz...");//打鼾  
        }  
    }  
}  

这样的代码用if else来做状态转换, 为我们的拓展带来困难. 状态模式就是要把这些if else 分支封装到不同的状态中, 并且把状态的转换局部化. 而促使状态发生变化的, 可能是外部因素, 也可能是用户的行为.

基础代码:


view plaincopy to clipboardprint?
//状态接口  
package designpattern.state;  
  
public interface State {  
    void handle(Context context);  
}  
//状态1  
package designpattern.state;  
  
public class ConcreteStateA implements State{  
    String msg = "state a";  
    public void handle(Context context) {  
        System.out.println("Current state is " + msg + ", the state will be changed.");  
        context.setState(new ConcreteStateB());  
    }  
}  
//状态2  
package designpattern.state;  
  
public class ConcreteStateB implements State{  
    String msg = "state b";  
    public void handle(Context context) {  
        System.out.println("Current state is " + msg + ", the state will be changed.");  
        context.setState(new ConcreteStateA());  
    }  
}  
//环境  
package designpattern.state;  
  
public class Context {  
      
    private State state;  
  
    public Context(ConcreteStateA s) {  
        setState(s);  
    }  
  
    public State getState() {  
        return state;  
    }  
  
    public void setState(State state) {  
        this.state = state;  
    }  
      
    public void request(){  
        state.handle(this);  
    }  
      
}  
//测试用例  
package designpattern.state;  
  
public class Test {  
    public static void main(String[] args){  
        Context c = new Context(new ConcreteStateA());  
        c.request();  
        c.request();  
        c.request();  
        c.request();  
        c.request();  
    }  
}  

举例:很多网站比如google,163在用户进入主页面的时候,右上角显示登陆按钮/链接,当用户登录后再回 到主页面,右上角会显示注销按钮,其实这就是一个状态的变迁。用户的行为(访问页面,登陆,注销等等)驱使状态发生变化,而状态的变化驱使页面的表现发生 了变化。就用伪jsp/servlet来实现一个状态模式。


view plaincopy to clipboardprint?
//状态接口  
package designpattern.state.login;  
public interface UserState {  
    public void handle(IndexServlet s);  
}  
//登陆状态  
package designpattern.state.login;  
  
public class LoginState implements UserState{  
    public void handle(IndexServlet s) {  
        System.out.println("当前用户状态是登录状态,您将看到注销按钮。");  
        if(s.getAction().equals("logout")){  
            s.setState(new LogoutState());  
        }  
    }  
}  
//注销状态  
package designpattern.state.login;  
  
public class LogoutState implements UserState{  
    public void handle(IndexServlet s) {  
        System.out.println("当前用户状态是未登录状态,您将看到登陆按钮。");  
        if(s.getAction().equals("login")){  
            s.setState(new LoginState());  
        }  
    }  
}  
//servlet  
package designpattern.state.login;  
  
public class IndexServlet {  
    private UserState state;  
    private String action;  
    public String getAction() {  
        return action;  
    }  
    public void setAction(String action) {  
        this.action = action;  
    }  
    public UserState getState() {  
        return state;  
    }  
    public void setState(UserState state) {  
        this.state = state;  
    }  
    //servlet第一次被实例化的时候处于未登录状态  
    public IndexServlet(){  
        setState(new LogoutState());  
        action = "";  
    }  
    public void request(String action){  
        this.action = action;  
        state.handle(this);  
    }  
    public void request(){  
        state.handle(this);  
    }  
}  
//测试用例 模拟servlet容器  
package designpattern.state.login;  
public class Container {  
    public static void main(String[] args){  
        IndexServlet s = new IndexServlet();  
        //用户第一次直接到主页面  
        s.request();  
        //用户有登陆请求  
        s.request("login");  
        //。。。  
        s.request("logout");  
        s.request("login");  
        s.request("logout");  
    }  
}  

特点:

1 对象在不同状态下的行为被分装到不同的状态类中;
2 对象状态的装换局部化。

优点:将特定状态的行为局部化,并将不同的状态的行为分割开。说白了就是消除了庞大的状态条件分支判断语句,而把状态的变迁分散转移到各个子类中去。

适用场景:当对象的行为取决于状态,并且在运行时根据状态来改变行为时。


转自:http://blog.csdn.net/sunxing007/archive/2010/03/28/5423789.aspx

  评论这张
 
阅读(582)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017