zoukankan      html  css  js  c++  java
  • 设计模式(二十一)—— 状态模式

    模式简介


    允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

    在某些情况下,一个对象的行为取决于它当前所处的状态,当对象属性(状态)在系统运行过程中发生变化,它呈现出的行为也随之发生改变。例如可调节亮度的台灯,假设灯光亮度分为三级,每次按下按钮,台灯会根据当前亮度增加一级,若已经是最亮的状态,按下按钮则关闭台灯。

    结构分析


    UML类图

    角色说明

    • Context

    环境类。客户端操作的类,包含一个IState类型的对象,保存其当前状态。

    • IState

    状态接口。定义一个统一的接口以封装与Context的特定状态相关的行为。

    • ConcreteState

    具体状态。实现状态接口,表示Context某个状态相关的行为。

    工作原理

    Context类将与状态相关的请求委托给ConcreteState对象处理,并将自身以参数形式传递给ConcreteState对象,如此,便可以在处理完请求后访问Context的SetState方法为Context设置新的状态。

    结构代码

    //环境类
    class Context
    {
        private IState _state;
        public Context(IState state)
        {
            _state = state;
            Console.WriteLine($"Initialize state -> {state}");
        }
    
        public void SetState(IState state)
        {
            _state = state;
            Console.WriteLine($"Set State -> {state}");
        }
    
        public void Request()
        {
            _state.Handle(this);
        }
    }
    
    //状态接口
    interface IState
    {
        void Handle(Context context);
    }
    
    //具体状态类A
    class ConcreteStateA : IState
    {
        public void Handle(Context context)
        {
            context.SetState(new ConcreteStateB());
        }
    }
    
    //具体状态类B
    class ConcreteStateB : IState
    {
        public void Handle(Context context)
        {
            context.SetState(new ConcreteStateA());
        }
    }
    
    //客户端调用
    static void Main(string[] args)
    {
        Context context = new Context(new ConcreteStateA());
        for (int i = 0; i < 5; i++)
        {
            context.Request();
        }
        Console.ReadLine();
    }
    

    程序输出:

    示例分析


    本节模拟第一节中提到的台灯示例。首先创建台灯类Lamp,提供共有方法SetState设置当前状态,包含一个保存当前状态的私有字段_state,并通过Request方法调用该状态的下台灯发光的行为。

    class Lamp
    {
        private IState _state;
        public Lamp(IState state)
        {
            _state = state;
            Console.WriteLine($"Initialize state -> {state}");
        }
        public void SetState(IState state)
        {
            _state = state;
            Console.WriteLine($"Set State -> {state}");
        }
    
        public void Request()
        {
            _state.Handle(this);
        }
    }
    

    声明状态接口,并分别实现具体状态类,这里包括四种状态Closed、Dim、Medium、Bright。

    interface IState
    {
        void Handle(Lamp context);
    }
    
    class Closed : IState
    {
        public void Handle(Lamp context)
        {
            context.SetState(new Dim());
        }
    }
    
    class Dim : IState
    {
        public void Handle(Lamp context)
        {
            context.SetState(new Medium());
        }
    }
    
    class Medium : IState
    {
        public void Handle(Lamp context)
        {
            context.SetState(new Bright());
        }
    }
    
    class Bright : IState
    {
        public void Handle(Lamp context)
        {
            context.SetState(new Closed());
        }
    }
    

    客户端调用,将台灯的初始状态设置为Closed,并连续调用,输出台灯状态。

    class Program
    {
        static void Main(string[] args)
        {
            Lamp lamp = new Lamp(new Closed());
            for (int i = 0; i < 10; i++)
            {
                lamp.Request();
            }
            Console.ReadLine();
        }
    }
    

    程序输出:

    适用场景


    • 一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。

    • 一个操作中含有大量的分支的条件语句,且这些分支依赖于该对象的状态。

  • 相关阅读:
    javascript往textarea追加内容
    Java之Comparable接口和Comparator接口
    Java之iterator迭代器和iterable接口
    Java之hashSet实现引用类型的禁止重复功能
    Java之获取系统属性
    Java之String,StringBuffer,StringBuilder类
    Java之sleep和wait的区别
    Android开发之ADT中无Annotation Processin的解决办法
    Android开发之注解式框架ButterKnife在ADT中的设置
    Android开发UI之Action Bar
  • 原文地址:https://www.cnblogs.com/Answer-Geng/p/9319827.html
Copyright © 2011-2022 走看看