zoukankan      html  css  js  c++  java
  • 状态模式 详解

    定义

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

    行为型模式

    角色

    • 上下文环境(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. 结构和实现都较为复杂,如果使用不当将会导致程序结构和代码的混乱;
      对“开闭原则”的支持并不太好,对于可以切换状态的的状态模式,增加新的状态类需要修改那些负责状态转换的代码,否则无法切换到新增状态,而且修改某个状态类的行为需要修改对应类的代码;
  • 相关阅读:
    C# 从需要登录的网站上抓取数据
    mysql
    Fiddler抓取https设置详解(图文)
    Handlebars块级Helpers
    SQL优化技巧
    MyBatis持久层框架使用总结
    网页刷新页面方法小结
    史上最全的程序猿面试资料
    ActiveMQ开发与简介
    Lex使用指南
  • 原文地址:https://www.cnblogs.com/George1994/p/6037702.html
Copyright © 2011-2022 走看看