概念
描述: 在该模式中,类的行为基于它的状态改变。这种类型的设计模式属于行为型设计模式。
在状态模式中,我们创建表示各种状态的对象和一个随着状态改变而改变的上下文。
- 意图 : 允许对象在内部状态改变时,改变它的行为,这个对象本身看起来好像修改了它的类。
- 主要解决 : 对象行为依赖于它的状态,并且可以根据状态改变而改变其行为
- 何时使用 : 在代码中包含大量对象状态有关的条件语句
- 解决方案 : 将各种具体的状态抽象出来
JS状态模式
1.新建一个index.js
点击查看代码
/**
* 状态类
*/
class State {
constructor(process) {
this.process = process
}
/**
* 处理状态的方法
* @param {*} context 状态上下文
*/
handle(context) {
//处理具体该流程的业务逻辑
console.log(`物品正处于【${this.process}】状态`)
//设置下一个状态
context.setState(this)
}
}
/**
* 状态上下文
*/
class Context {
/**
* 构造函数
*/
constructor() {
this.state = null
}
/**
* 获取状态
* @returns 返回当前状态
*/
getState() {
return this.state
}
/**
* 赋值状态
* @param{*} state 状态
*/
setState(state) {
this.state = state
// console.log(`当前上下文的状态为:${state}``);
}
}
2.调用代码如下:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="./StatePattern.js"></script>
<title>Document</title>
</head>
<body>
<script>
var context = new Context();
var order = new State("ordering");
var send = new State("sending");
order.handle(context)
send.handle(context)
</script>
</body>
</html>
C# 实现状态模式
1.创建状态机(Work)
点击查看代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace StatePattern.Console
{
/// <summary>
/// 状态机
/// </summary>
public class Work
{
private State _currentstate;
private int _processId;
private bool _finish = false;
public bool Finish { get => _finish; set => _finish = value; }
public int ProcessId { get => _processId; set => _processId = value; }
public Work(State state)
{
this._currentstate = state;
_processId = state.StateId;
}
/// <summary>
/// 设置状态机中的状态
/// </summary>
/// <param name="state"></param>
public void SetState(State state)
{
_currentstate = state;
_processId = state.StateId;
}
/// <summary>
/// 执行节点中的Do方法(代理模式)
/// </summary>
/// <param name="func"></param>
public void Do(Func<int, bool> func)
{
_currentstate.Do(this, func);
}
}
}
主要目的获取当前状态,存储当前状态id(ProcessId),将当前的状态复制给私有字段,通过当前的状态触发不同的业务逻辑处理
2.创建状态抽象类(State)
点击查看代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace StatePattern.Console
{
/// <summary>
/// 状态
/// </summary>
public abstract class State
{
public abstract int StateId { get; }
public abstract void Do(Work work, Func<int, bool> func);
}
}
这个类的作用是保存当前状态id,Do方法(传委托的意义在于:判断当前属于哪个状态流程,触发不同的业务处理)
3.创建一个下单状态(OrderState)
OrderState
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace StatePattern.Console
{
public class OrderState : State
{
public override int StateId => 1;
public override void Do(Work work, Func<int, bool> func)
{
//判断状态机是否处于结束状态
if (!work.Finish)
{
// 判断条件是否满足
if (func(work.ProcessId))
{
// ...处理流程需要在该状态处理的逻辑
System.Console.WriteLine("do order");
// return work.ProcessId + 1;
}
//设置下一个State
work.SetState(new SendState());
//执行下一个State的Do方法
work.Do(func);
}
else
{
//否则执行finish
work.SetState(new FinishState());
work.Do(func);
}
}
}
}
判断当前传入的状态机是否是完结状态,委托的作用:当前指定的状态id是否与传入的状态id一致,一致则处理对应的业务,不一致则处理下一个状态的业务,下面的处理逻辑基本和上面的一致,就不多介绍了
一个状态处理完毕,处理下一个状态,最后执行完结状态处理方法
4.发送货物的类(SendState)
SendState
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace StatePattern.Console
{
public class SendState : State
{
public override int StateId => 2;
public override void Do(Work work, Func<int, bool> func)
{
//判断状态机是否处于结束状态
if (!work.Finish)
{
// 判断条件是否满足
if (func(work.ProcessId))
{
// ...处理流程需要在该状态处理的逻辑
System.Console.WriteLine("do sending");
}
//设置下一个State
work.SetState(new FinishState());
//执行下一个State的Do方法
work.Do(func);
}
else
{
//否则执行finish
work.SetState(new FinishState());
work.Do(func);
}
}
}
}
5.完成状态方法:
点击查看代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace StatePattern.Console
{
public class FinishState : State
{
public override int StateId => 3;
public override void Do(Work work, Func<int, bool> func)
{
work.Finish = true;
System.Console.WriteLine("流程结束");
}
}
}