Squirrel ステート マシン - 原理の探索からベスト プラクティスまで

著者: JD Logistics Zheng Penghui

1 はじめに

Squirrel ステート マシンは、オブジェクトの動作モデリング用のツールであり、主にオブジェクトがそのライフ サイクルで経験する状態と、外界からのさまざまなイベントへの対応方法を記述します。たとえば、注文の作成、支払い、配送、収穫、キャンセルなどのステータス、状態間の制御、およびトリガー イベントの監視は、このフレームワークによって明確に管理および実現できます。ステート マシンを使用してオブジェクトのライフ フローを管理する利点は、コードの保守性とテスト容易性にさらに反映されます. 明確な状態条件、原子応答アクション、およびイベント駆動型の移行ターゲット状態は、複雑で複雑なビジネス シナリオに使用できます。変更可能なプロセス. メンテナンスとテストの難しさを大幅に軽減.

2 基本概念

2.1 Squirrel ステートマシンの定義

Squirrel ステート マシンは有限ステート マシンです. 有限ステート マシンとは、オブジェクトに明確で複雑なライフ フロー (通常は 3 つ以上の状態) があり、状態遷移にはさまざまなトリガー条件と処理動作があることを意味します。

2.2 リス状態機械要素

Squirrel ステート マシンは、現在の状態、状態、アクション、次の状態の 4 つの要素に要約できます。「現状」と「条件」が原因で、「行動」と「次の状態」が結果です。

  • 現在の状態: 現在の状態を指します。
  • 条件: イベントとも呼ばれます。条件が満たされると、アクションがトリガーされるか、状態遷移が実行されます。
  • アクション: 条件が満たされた後に実行されるアクション。アクションの実行後、新しい状態に移行するか、元の状態のままにすることができます。Actions are not required. 条件が満たされている場合、アクションを実行せずに新しい状態に直接移行できます。
  • 次の状態: 条件が満たされた後に移行する新しい状態。「二次状態」は「現在の状態」に対する相対的なものであり、「二次状態」が活性化されると、新たな「現在の状態」に変化します。

3 実施原則

3.1 店舗監査 CASE

たとえば、JD.com のオンライン ストアを開店するには、正式に開始する前に審査が必要です. ストアのステータスは、審査待ち、却下、および審査済みです. 対応する操作には、審査の送信、承認、および審査の却下があります. ここで、ストア レビュー プロセスの要件を実現する必要があります。

3.2 スキームの比較

3.2.1 一般的に使用される if-else または switch-case の実装 (ブランチ モード)

図 1. if-else/switch-case モード実装のフローチャート

3.2.2 ステートマシンの実装


 

図 2. ステート マシン モードの実装フローチャート

3.2.3 比較

ステート マシンを導入することで、多数の if-else if-else または switch-case 分岐構造を削除でき、現在の状態と状態駆動テーブルを介して動作駆動テーブルを直接クエリして、特定の動作を見つけることができます。コードのメンテナンスと拡張に役立つ操作を実行します。

3.3 実施原則

 

図 3. ステート マシン作成のフローチャート

 

  • StateMachine: The StateMachine instance is created by StateMachineBuilder and is not shared. 注釈 (または流暢な API) によって定義された StateMachine の場合、StateMachine インスタンスはこの定義に従って作成され、対応するアクションもこのインスタンスによって実行されます。 with spring は、Spring について話すことです。bean インスタンスは、ビルダーによって作成されたステート マシン インスタンスに注入されます。
  • StateMachineBuilder: 基本的に、StateMachineBuilderFactory によって作成される動的プロキシです。プロキシされた StateMachineBuilder のデフォルトの実装は StateMachineBuilderImpl です。これは、ステート、イベント、コンテキスト タイプ情報、コンストラクタなどを含むステート マシン インスタンス作成の詳細を内部的に記述し、StateConverter、EventConverter、 MvelScriptManager など StateMachineBuilder は再利用でき、使用中のシングルトンとして実装できます。
  • StateMachineBuilderFactory: StateMachineBuilder 用に作成された動的プロキシ インスタンス。

4 共有の練習

4.1 環境依存性

<dependency>
<groupId>org.squirrelframework</groupId>
<artifactId>squirrel-foundation</artifactId>
<version>0.3.9</version>
</dependency>

4.2 状態機械要素の定義: 状態、イベント

// 店铺审核状态
public Enum ShopInfoAuditStatusEnum{
audit(0,"待审核"),
agree(1,"审核通过"),
reject(2,"审核驳回");
}
// 店铺审核事件
public Enum ShopInfoAuditEvent{
SUBMIT, // 提交
AGREE, // 同意
REJECT; // 驳回
}

 

4.3 StateMachineBuilder インスタンスの構築

/**
* StateMachineBuilder实例
*/
public class StateMachineEngine <T extends UntypedStateMachine, S, E, C> implements ApplicationContextAware{


private ApplicationContext applicationContext;


private static Map<String,UntypedStateMachineBuilder> builderMap = new HashMap<String,UntypedStateMachineBuilder>();

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}


@Transactional
public void fire(Class<T> machine, S state, E event, C context) {
StateMachineBuilder stateMachineBuilder = this.getStateMachineBuilder(machine);
StateMachine stateMachine = stateMachineBuilder.newStateMachine(state,applicationContext);
stateMachine.fire(event, context);
}


private StateMachineBuilder getStateMachineBuilder(Class<T> stateMachine){
UntypedStateMachineBuilder stateMachineBuilder = builderMap.get(stateMachine.getName());
if(stateMachineBuilder == null){
stateMachineBuilder = StateMachineBuilderFactory.create(stateMachine,ApplicationContext.class);
builderMap.put(stateMachine.getName(),stateMachineBuilder);
}
return stateMachineBuilder;

4.4 特定のストア ステータス レビュー ステート マシンを作成する

/**
* 店铺审核状态机
*/
@States({
@State(name = "audit"),
@State(name = "agree"),
@State(name = "reject")
})
@Transitions({
@Transit(from = "audit", to = "agree", on = "AGREE", callMethod = "agree"),
@Transit(from = "audit", to = "reject", on = "REJECT", callMethod = "reject"),
@Transit(from = "reject", to = "audit", on = "SUBMIT", callMethod = "submit"),
@Transit(from = "agree", to = "audit", on = "SUBMIT", callMethod = "submit"),
@Transit(from = "audit", to = "audit", on = "SUBMIT", callMethod = "submit"),
})
@StateMachineParameters(stateType=ShopInfoAuditStatusEnum.class, eventType=ShopInfoAuditEvent.class, contextType=ShopInfoAuditStatusUpdateParam.class)
public class ShopInfoAuditStateMachine extends AbstractUntypedStateMachine {


private ApplicationContext applicationContext;


public ShopInfoAuditStateMachine(){}


public ShopInfoAuditStateMachine(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}


// 审核通过业务逻辑
public void agree(ShopInfoAuditStatusEnum fromState, ShopInfoAuditStatusEnum toState, ShopInfoAuditEvent event, ShopInfoAuditStatusUpdateParam param) {
this.agree(fromState,toState,event,param);
}

// 审核驳回业务逻辑
public void reject(ShopInfoAuditStatusEnum fromState, ShopInfoAuditStatusEnum toState, ShopInfoAuditEvent event, ShopInfoAuditStatusUpdateParam param) {
this.reject(fromState,toState,event,param);
}

// 提交业务逻辑
public void submit(ShopInfoAuditStatusEnum fromState, ShopInfoAuditStatusEnum toState, ShopInfoAuditEvent event, ShopInfoAuditStatusUpdateParam param) {
this.submit(fromState,toState,event,param);
}

 

4.5 クライアントの呼び出し

// 调用端
main{
StateMachineEngine stateMachineEngine = applicationContext.getBean(StateMachineEngine.class);
// 审核通过调case
stateMachineEngine.fire(ShopInfoAuditStateMachine.class,ShopInfoAuditStatusEnum.audit,ShopInfoAuditEvent.AGREE,param);
// 审核驳回case
stateMachineEngine.fire(ShopInfoAuditStateMachine.class,ShopInfoAuditStatusEnum.audit,ShopInfoAuditEvent.REJECT,param);
}

 

5 まとめ

ステート マシンは、オブジェクトの状態の流れ、イベントの監視、およびさまざまな外部イベントへの応答を処理するのに役立ちます。コード設計の観点からは、多数の if-else/switch-case ロジックの判断が削減され、コードの保守性とスケーラビリティが向上し、管理とテストが容易になります。

{{o.name}}
{{m.name}}

おすすめ

転載: my.oschina.net/u/4090830/blog/6822669