状态模式 详解

定义

当一个对象在内在状态改变时允许改变其行为,这个对象看起来像是改变了其类;

行为型模式

角色

  • 上下文环境(Context):定义了客户程序需要的接口并维护了一个具体状态角色的实例,将与状态相关的操作委托给当前的Concrete State对象来处理;
  • 抽象状态(State):定义了一个接口以封装使用上下文环境的一个特定状态相关的行为;
  • 具体状态(Concrete State): 实现抽象状态定义的接口;

从网上找到的例图
enter image description here


适用场景

  • 当一个对象的行为取决于它的状态,并且它必须在运行的时候根据状态改变它的行为时;
  • 一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态(代码中包含大量与对象状态有关的条件语句);

例子


实现代码

/**
 * Created by George on 16/7/10.
 */
//电梯状态
function LiftState () {
    this._context = null;
    this.setContext = function (context) {
        this._context = context;
    };
    // 开门
    this.open = function () {

    };
    // 关门
    this.close = function () {

    };
    // 运行
    this.running = function () {

    };
    // 停止
    this.idle = function () {

    };
};

//环境类
function Context () {
    this._openState = new OpenState();
    this._closeState = new CloseState();
    this._runningState = new RunningState();
    this._idleState = new IdleState();

    // 获取和设置状态
    this._liftState = new LiftState();
    this.getLiftState = function () {
        return this._liftState;
    };
    this.setLiftState = function (state) {
        this._liftState = state;
        this._liftState.setContext(this);
    };

    // 更改状态
    this.open = function () {
        this._liftState.open();
    };
    this.close = function () {
        this._liftState.close();
    };
    this.running = function () {
        this._liftState.running();
    };
    this.idle = function () {
        this._liftState.idle();
    };
};

// 具体开门状态
function OpenState () {

};
OpenState.prototype = new LiftState();
OpenState.prototype.close = function () {  // 开门后会关闭
    this._context.setLiftState(this._context._closeState);
    this._context.getLiftState().close();
    console.log("open to close");
};

// 关门状态
function CloseState () {

};
CloseState.prototype = new LiftState();
CloseState.prototype.running = function () {  // 开门后可能会运行
    this._context.setLiftState(this._context._runningState);
    this._context.getLiftState().running();
    console.log("close to running");
};
CloseState.prototype.idle = function () {  // 开门后可能空闲
    this._context.setLiftState(this._context._idleState);
    this._context.getLiftState().idle();
    console.log("close to idle");
};

// 运行状态
function RunningState () {

};
RunningState.prototype = new LiftState();
RunningState.prototype.idle = function () {  // 运行后可能会空闲下来
    this._context.setLiftState(this._context._idleState);
    this._context.getLiftState().idle();
    console.log("running to idle");
};

// 空闲状态
function IdleState() {

};
IdleState.prototype = new LiftState();
IdleState.prototype.open = function () {  //空闲之后会开门
    this._context.setLiftState(this._context._openState);
    this._context.getLiftState().open();
    console.log("idle to open");
};


// 主函数
var context = new Context();
context.setLiftState(new IdleState());

// 大概操作的意思是先处于限制状态,然后再开门,关上门,然后运行,到达后至于限制,最后开门
context.open();
context.close();
context.running();
context.idle();
context.open();

实现结果:
这里写图片描述


优缺点

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值