JAVA23种设计模式之状态模式

  1. 状态模式
    状态模式允许一个对象在其内部状态发送改变时,改变其行为,看上去就像是改变了他的类一样。
    状态模式要求我们把对象的行为放到对象不同的状态中。随着状态的改变对象的行为也随之发生改变。另外重要的一点是,我们研究的对象要持有所有的状态,在状态类中是通过对象来改变其自身的状态的。
  2. 状态模式的示意图
    状态模式
  3. 状态模式包含的角色
    环境角色:持有所有自身所有的状态。而且,该类中也定义了当前对象转换状态的操作。也就是通过这些方法来返回当前对象的具体状态。
    **抽象状态角色:**定义一个接口供所有具体状态实现。里面定义了状态转换的操作方法。也就是一系列动作,例如:酒店需要通过预定或者入住,才能将房间的状态的转变为已预订状态和已入住状态,这里的预定和入住的方法就需要定义在这个抽象角色中,供具体状态角色实现。
    具体状态角色:持有环境角色。 每个具体状态角色都实现了该状态下,环境角色的所有行为。
  4. 状态模式示例代码
    场景:日常生活中餐厅为例,你如果想去吃饭,则需要提前预定,然后前往吃饭,吃完饭付完钱就可以释放当前餐桌。既然预定了,也可以退订。这里涉及到的餐桌状态就有,已预订状态,已占用状态(这里占用指的是现场有人在吃饭!),空闲状态。
    注意:在这里我们要分清楚对象的状态和改变对象状态的操作。
    环境角色: (餐桌)
  public class Table {
    public State bookedState;
    public State freeState;
    public State occupiedState;
    private State state ;
    public Table() {
        bookedState = new BookedState(this);
        freeState = new FreeState(this);
        occupiedState = new OccupiedState(this);
        state = freeState;//初始为空闲
    }
    public void setState(State state) {
        this.state = state;
    }
    /**
     * 预定
     */
    public  void book(){
        state.book();
    }
    /**
     * 退订
     */
    public void Unsubscribe(){
        state.Unsubscribe();
    }
    /**
     * 吃饭
     */
    public void eat(){
        state.eat();
    }
    /**
     * 付钱走人
     */
    public void payMoneyAndLeave(){
        state.payMoneyAndLeave();
    }
}

抽象状态角色:

public interface State {
    /**
     * 预定
     */
    void book();
    /**
     * 退订
     */
    void Unsubscribe();
    /**
     * 吃饭
     */
    void eat();
    /**
     * 付钱走人
     */
    void payMoneyAndLeave();
}

具体状态角色:(各种状态)
空闲状态:

public class FreeState implements State {
    private Table table;
    public FreeState(Table table) {
        this.table = table;
    }
    @Override
    public void book() {
        System.out.println("您已经成功预订了...");
        table.setState(table.bookedState);
    }
    @Override
    public void Unsubscribe() {
    }
    @Override
    public void eat() {
        System.out.println("您已经成功开始等菜...");
        table.setState(table.occupiedState);
    }
    @Override
    public void payMoneyAndLeave() {

    }
}

预定状态:

public class BookedState implements State{
    private Table table;
    public BookedState(Table table) {
        this.table = table;
    }
    @Override
    public void book() {
    }
    @Override
    public void Unsubscribe() {
        System.out.println("您已经成功取消预订了...");
        table.setState(table.freeState);
    }
   @Override
    public void eat() {
        System.out.println("您已经到达餐厅吃饭...");
        table.setState(table.occupiedState);
    }
    @Override
    public void payMoneyAndLeave() {

    }
}

占用状态:(指到现场吃饭)

public class OccupiedState implements State {
    private Table table;
    public OccupiedState(Table table) {
        this.table = table;
    }
    @Override
    public void book() {
    }
    @Override
    public void Unsubscribe() {
        System.out.println("您已经成功取消了预订了...");
        table.setState(table.freeState);
    }
    @Override
    public void eat() {
    }
    @Override
    public void payMoneyAndLeave() {
        System.out.println("您已经付完钱离开...");
        table.setState(table.freeState);
    }
}

测试主函数:

public class Main {
    public static void main(String[] args) {
       Table table =  new Table();
       table.book();
       table.eat();
       table.payMoneyAndLeave();
       System.out.println("----------------------------------");
       table.eat();
       table.payMoneyAndLeave();
    }
}
  1. 状态模式的优缺点
  • 优点:
  • 封装了转换规则。
  • 枚举了对象几乎所有的状态。
  • 将所有与某个状态相关的行为或者是方法放到一个类中,可以很方便的增加新的状态,只需要该表状态的行为即可。
  • 减少了代码中的if…else…的使用。
  • 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
  • 缺点:
  • 会增加系统的类和对象的个数。
  • 状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。
  • 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
发布了62 篇原创文章 · 获赞 8 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/system_obj/article/details/86709646