设计模式 - 状态模式

状态模式:当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。
核心:当前状态决定当前行为,行为执行后又可能导致状态的转换
角色:

  • Context上下文容器:维护所有的状态和行为,是面向客户的入口
  • Status对象:保存状态对应的行为。
  • Machine状态机:维护状态的转换关系when(行为,状态) -> next状态:do(next行为)

由status对象在行为中完成状态转换

Context

// 上下文信息,用于维护所有状态对象以及当前状态信息,同时作为客户端的访问入口
public class Context implements IStatus{
    // 更正一下设计模式之禅中对状态机的示例:其状态对象使用了final static,但是状态对象又持有了context对象引用,必然会出现并发问题
    protected final IStatus OPEN = new OpenStatus(this);
    protected final IStatus STOP_CLOSE = new StopStatus(this);
    protected final IStatus RUN = new RunStatus(this);

    private IStatus status = null;

    public Context() {
        this.status = STOP_CLOSE;
    }

    protected void setStatus(IStatus status) {this.status = status;}

    // 具体行为委托给status对象执行
    @Override
    public void run() {this.status.run();}

    @Override
    public void stop() {this.status.stop();}

    @Override
    public void open() {this.status.open();}

    @Override
    public void close() {this.status.close();}
}

Status

// 抽象状态对象,提供公共的默认实现(由于在状态内部进行状态流转,因此还需持有context上下文信息)
public abstract class AbstractStatus implements IStatus{

    protected Context context = null;

    protected AbstractStatus(Context context){
        this.context = context;
    }

    @Override
    public void run() {System.out.println("command run - Do nothing!");}

    @Override
    public void stop() {System.out.println("command stop - Do nothing!");}

    @Override
    public void open() {System.out.println("command open - Do nothing!");}

    @Override
    public void close() {System.out.println("command close - Do nothing!");}
}

// 子类负责具体实现逻辑,重写该状态下支持的行为,并设置状态转换。
public class OpenStatus extends AbstractStatus{
    public OpenStatus(Context context) {
        super(context);
    }

    @Override
    public void open() {
        System.out.println("command open - keep open");
    }

    @Override
    public void close() {
        System.out.println("command close - close the door");
        this.context.setStatus(this.context.STOP_CLOSE);
    }
}

状态机实现状态模式

Context

// 用于维护当前状态信息,以及使用状态机完成状态转换,作为客户端的访问入口
public class Context implements IStatus {
    private AbstractStatus status = null;

    public Context() {
        this.status = StatusMechine.STOP_CLOSE_STATUS;
    }

    protected void setStatus(AbstractStatus status) {
        this.status = status;
    }

    // 将命令委托给具体的状态对象进行处理,并将当前状态和执行行为交由状态机完成状态转换
    @Override
    public void run() {
        this.status.run();
        this.status = StatusMechine.trans(this.status,StatusMechine.RUN_ACTION);
    }

    @Override
    public void stop() {
        this.status.stop();
        this.status = StatusMechine.trans(this.status,StatusMechine.STOP_ACTION);
    }

    @Override
    public void open() {
        this.status.open();
        this.status = StatusMechine.trans(this.status,StatusMechine.OPEN_ACTION);
    }

    @Override
    public void close() {
        this.status.close();
        this.status = StatusMechine.trans(this.status,StatusMechine.CLOSE_ACTION);
    }
}

StatusMechine

public class StatusMechine{
    // 行为类型
    protected final static String RUN_ACTION = "RUN";
    protected final static String STOP_ACTION = "STOP";
    protected final static String OPEN_ACTION = "OPEN";
    protected final static String CLOSE_ACTION = "CLOSE";

    // 状态类型
    protected final static AbstractStatus OPEN_STATUS = new OpenStatus();
    protected final static AbstractStatus STOP_CLOSE_STATUS = new StopStatus();
    protected final static AbstractStatus RUN_STATUS = new RunStatus();

    // 状态流转表
    protected static Map<String,AbstractStatus> transMap = new HashMap<>();

    // 状态转换
    public static AbstractStatus trans(AbstractStatus status, String actions) {
        String key = status.getStatusName() + actions;
        return transMap.getOrDefault(key, status);
    }

    // 状态转换过程注册方法
    protected static void registerStatusTrans(AbstractStatus status, String action, AbstractStatus nextStatus){
        transMap.put(status.getStatusName() + action, nextStatus);
    }

    // 将状态的转换注册到状态机中
    static {
        StatusMechine.registerStatusTrans(StatusMechine.RUN_STATUS, StatusMechine.STOP_ACTION, StatusMechine.STOP_CLOSE_STATUS);
        StatusMechine.registerStatusTrans(StatusMechine.STOP_CLOSE_STATUS, StatusMechine.RUN_ACTION, StatusMechine.RUN_STATUS);
        StatusMechine.registerStatusTrans(StatusMechine.STOP_CLOSE_STATUS, StatusMechine.OPEN_ACTION, StatusMechine.OPEN_STATUS);
        StatusMechine.registerStatusTrans(StatusMechine.OPEN_STATUS, StatusMechine.CLOSE_ACTION, StatusMechine.STOP_CLOSE_STATUS);
    }
}

Status

// 抽象状态对象,提供公共的默认实现
public abstract class AbstractStatus implements IStatus {
    public abstract String getStatusName();

    @Override
    public void run() {System.out.println("command run - Do nothing!");}

    @Override
    public void stop() {System.out.println("command stop - Do nothing!");}

    @Override
    public void open() {System.out.println("command open - Do nothing!");}

    @Override
    public void close() {System.out.println("command close - Do nothing!");}
}

// 具体实现子类,只需专注于具体指令的实现逻辑,而无需关心状态转换过程
public class OpenStatus extends AbstractStatus {
    @Override
    public String getStatusName() {
        return "OPEN";
    }

    @Override
    public void open() {
        System.out.println("command open - keep open");
    }

    @Override
    public void close() {
        System.out.println("command close - close the door");
    }
}
posted @ 2020-12-01 21:13  祁奇  阅读(70)  评论(0编辑  收藏  举报