情状形式

摘要

本文以 Java 和 C# 示例表达意况格局的定义和利用场景。

定义

状态形式(state pattern)允许对象在其中景况改变时改变它的行事,
对象看起来好像修改了它的类。

图片 1

解读

  • 表现依照情形改变,不一致的景观有差其余作为

现象举例

  • 机关贩卖机
  • 家用电表

情景格局和政策情势

  • 方针方式围绕能够沟通的算法举行工作操作
  • 处境方式通过改变目的的其中景况来帮助对象说了算自己的作为
  • 情况格局将相继状态所对应的操作分离开来,即对于差距的事态,由分歧的子类达成具体操作,差别意况的切换由子类达成,当发现传入参数不是团结这几个场合所对应的参数,则要好给Context类切换状态;而策略格局是平素信赖注入到Context类的参数举行抉择策略,不存在切换状态(取自博客园网友的答疑)

上边用代码示例举行求证:

代码示例

Java代码

// 状态接口
public interface ManState {
    String NextBehavior();
}

// 状态-早上醒来
public class Wakeup implements ManState {
    @Override
    public String NextBehavior() {
        return "正在起床";
    }
}

// 状态-吃早餐
public class Eatting implements ManState {
    @Override
    public String NextBehavior() {
        return "正在吃早饭";
    }
}

// 状态-上班
public class Working implements ManState{
    @Override
    public String NextBehavior() {
        return "正在工作";
    }
}

// 状态-睡觉
public class Sleeping implements ManState{
    @Override
    public String NextBehavior() {
        return "正在睡觉";
    }
}

// 上下文 - Man
public class Man {

    private ManState state;

    public Man(){
        state = null;
    }

    // 设置状态
    public void setState(ManState state){
        this.state = state;
    }

    // 获取状态
    public ManState getState(){
        return state;
    }
}

public static void main(String[] args) throws Exception {

        //定义上下文
        Man man = new Man();

        // 醒了
        ManState state = new Wakeup();

        this.man.setState(state);
        this.man.getState().NextBehavior();

        // 吃饭
        state = new Eatting();

        this.man.setState(state);
        this.man.getState().NextBehavior();

        // 上班
        state = new Working();

        this.man.setState(state);
        this.man.getState().NextBehavior();

        //睡觉
        state = new Sleeping();

        this.man.setState(state);
        this.man.getState().NextBehavior();
}

地点的例证,以职工为例,说贝拉米天中做的政工,其状态是在外表举办控制的,事实上,根据必要,也足以在中间贯彻动静的转移,那就须求将上下文注入到现实况状的已毕中,以贯彻一个好像指针的效率。

public interface EmpState {
    void DoSomething(Employee emp);
}

public class Wakeup implements EmpState {
    @Override
    public void DoSomething(Employee emp) {
        System.out.println("起床了");
        emp.SetState(new Eatting());
    }
}

public class Eatting implements  EmpState {
    @Override
    public void DoSomething(Employee emp) {
        System.out.println("吃早饭呢");
        emp.SetState(new Working());
    }
}

public class Working implements EmpState {
    @Override
    public void DoSomething(Employee emp) {
        System.out.println("正在工作");
        emp.SetState(new Sleeping());
    }
}

public class Sleeping implements EmpState {
    @Override
    public void DoSomething(Employee emp) {
        System.out.println("正在睡觉");
        System.out.println("没有其他状态了");
    }
}

public class JavaStateDemo {

    public static void main(String[] args) {

        EmpState state = new Wakeup();

        //需要一个初始状态
        Employee emp = new Employee(state);

        emp.Go();
        emp.Go();
        emp.Go();
        emp.Go();
    }
}

这几个事例从里边改变Employee的景况,以贯彻分化的一言一行。

员工请假/工作天数计算示例

考虑有以下场景:要求方一而再请假和非延续请假的拍卖方法是例外的,必要精通的通晓员工每个月的工作和请假情状,我们贯彻如下的气象操作模型

using System;

namespace StatePatternDemo
{
    // 抽象状态接口
    public interface IWorkState
    {
        void HandleWorkState(Employee emp);
    }

    // 请假
    public class Leaving:IWorkState
    {
        public void HandleWorkState(Employee emp)
        {
            System.Console.WriteLine($"{emp.Name} 请假 {emp.LeavingDays} 天");
            System.Console.WriteLine($"{emp.Name} 上次请假日期是 {emp.LastLeavingDate} ");
        }
    }

    // 工作
    public class Working:IWorkState
    {
        public void HandleWorkState(Employee emp)
        {
            System.Console.WriteLine($"{emp.Name} 正常上班中...");
            System.Console.WriteLine($"{emp.Name} 已连续工作 {Datetime.Now.Day - LastLeavingDate} 天");
        }

    }

    // 上下文
    public class Employee
    {
        // 职员姓名(标识)
        public string Name { get; set; }

        public double LeavingDays { get; set; } // 本次请假天数
        public Datetime LastLeavingDate { get; set; } // 上次请假日期
        public double TotalLeavingDays { get; set; } // 共请假天数

        // 工作天数
        public double WorkingDays { get; set; }

        //公休天数
        private int restDays { get; set;}

        private IWorkState WorkState;

        public Employee(IWorkState workState)
        {
            this.WorkState = workState;
        }

        public void SetState(IWorkState workState)
        {
            this.WorkState = workState;
        }

        /// <code>
        /// 上班签到或请假导致的状态改变
        /// </code>
        public void WorkingStateChanging(Employee emp)
        {
            this.WorkState.HandleWorkState(Employee emp);
        }
    }
}

如上代码中,我把前后文类变成了Employee对象,代表一个干部,这厮士有三种差其余事态,其中请假情状还足以细分为两次三番请假和非三番五次请假,也就是说,若是代码继续细化,我们还足以在这场所形式中再嵌套一个状态方式,以更精晓的描述要求。

namespace StatePatternDemo
{
    public interface ILeavingState
    {
        void Leaving(Employee emp);
    }


    public class NotContinusLeaving:ILeavingState
    {
        public void Leaving(Employee emp)
        {
            //非连续请假的实现逻辑
        }
    }

    public class ContinusLeaving:ILeavingState
    {
        public void Leaving(Employee emp)
        {
            //非连续请假的实现逻辑
        }
    }

    // 其他逻辑
}

小结:

  • 动静格局避免了代码中繁复的if/else/switch逻辑,使代码更易于阅读和尊敬
  • 将气象引起的更动独立封装在各自的落到实处中,所以它符合开闭原则

如上就是自身对气象方式的接头,认为我晓得的有难题的,可以在底下留言,谢谢大家!

相关文章