设计模式(20):状态模式 State

从编码体验来看,状态模式应该是写面对程序员的“外观模式”~

状态模式 State

状态模式允许一个对象在其内部状态改变的时候改变行为。这个对象看上去象是改变了它的类一样。状态模式把所研究的对象的行为包装在不同的状态对象里,每一个状态对象都属于一个抽象状态类的一个子类。状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。状态模式需要对每一个系统可能取得的状态创立一个状态类的子类。当系统的状态变化时,系统便改变所选的子类

###问题:

A monolithic object’s behavior is a function of its state, and it must change its behavior at run-time depending on that state. Or, an application is characterixed by large and numerous case statements that vector flow of control based on the state of the application.

###意图:

  • Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.
  • An object-oriented state machine
  • wrapper + polymorphic wrappee + collaboration

###代码

例:有时在网页上对一条数据进行一些操作(比如更新,隐藏等),可能实际上只是一个sql语句 update xx set state=?,而且进行操作之后还需要继续处理,比如隐藏之后实际上是加了个锁定状态,还要给它关联的记录加子状态,所以就不得不在代码里面加入 if(state==1){do something}else if(state==2){}……,状态模式就是加入了一些这样的机制,让代码看不来不这么挫。

代码1:状态接口,所有状态都需要实现,这里面写两个,用户激活以及冻结状态

/**
 * 状态,对象改变状态后的触发方法,以及状态ID,
 * */
public interface State {
    public void trigger(ObjectDao obj);
    public int getStateid();
}
//比如一个用户被激活
public class Active implements State{
    @Override
    public void trigger(ObjectDao obj) {
        System.out.println("Id为"+ obj.getId()+"的用户已经激活,正在做后续处理");
    }
    @Override
    public int getStateid() {
        return 1;
    }
}
//比如一个用户被冻结
public class Delete implements State{

    @Override
    public void trigger(ObjectDao obj) {
        System.out.println("Id为"+ obj.getId()+"的用户已经冻结,正在做后续处理");
    }

    @Override
    public int getStateid() {
        return 2;
    }
}

代码2:对象DAO,一般情况下做为一个父类,具体交给子类去扩展

public class ObjectDao {

    private int id;

    public int getId() {
        return id;
    }

    public ObjectDao(int id) {
        this.id = id;
    }
    public void set_state(State s){
        System.out.println("update table set state=" + s.getStateid()+"where id="+this.getId());
        s.trigger(this);
    }
}
public class User extends ObjectDao{
    public User(int id) {
        super(id);
    }
}

代码3:客户端调用

public class Client {
    public static void main(String[] args){
        User u = new User(45);
        u.set_state(new Active());
        u.set_state(new Delete());
    }
}

##小结

状态模式 State

  • 使用频率:
    一般不会向上面那么规范的搞个触发器什么的,但通过状态完成逻辑的代码还是会常写。

  • 利弊影响:
    经常碰到很多特殊状态要特殊处理的时候会觉得很有用,如果没有就会觉得烦。