UMLのステートマシン図を実装する for C# - その3
まえがき
今回は、前回説明したサンプルのエアコンステートマシンを実装していきます。
StateMachine クラス
StateMachine クラスを継承したステートマシンを実装します。
エアコンステートマシンでは、3 つのステートマシンを実装する必要があります。
名称 | 詳細 | 備考 |
---|---|---|
ModelStateMachine | エアコン全体のステートマシン | |
RunningStateMachine | Running 状態のサブステートマシン | |
CleanStateMachine | Clean 状態のサブステートマシン |
ModelStateMachine クラス
ModelStateMachine クラスは、エアコンモデルの AirConditioner クラス(後述)を引数として受け取るコンストラクタを定義します。
コンストラクタ内では、各状態(State)からモデルの処理を呼び出し可能にするため、エアコンモデルを Public プロパティにセットします。
その後、StateMachine クラスで定義された ChangeToInitalState メソッドを呼び出すことで初期状態への遷移を開始します。
また、継承元の StateMachine クラスで宣言された抽象メソッドの GetInitialState を定義し、ステートマシンの初期状態を返すようにします。
public class ModelStateMachine : StateMachine { // エアコンモデル public AirConditioner Model { get; } // コンストラクタ public ModelStateMachine(AirConditioner model) { this.Model = model; this.ChangeToInitialState(); } // 初期状態取得 protected override State GetInitialState() { return InitialState.Instance; } }
RunningStateMachine クラス
ModelStateMachine クラスはサブステートマシンなので、親である ModelStateMachine クラスを引数として受け取るコンストラクタを定義します。
コンストラクタでは、受け取った ModelStateMachine クラス、およびそこから取得できるエアコンモデル(AirConditioner クラス)を Public プロパティにセットします。
あとは ModelStateMachine クラスと同様、ChangeToInitialState メソッドの呼び出しと、GetInitialState メソッドの定義を行います。
RunningStateMachine の初期状態は、前回説明したとおり、Cool 状態となります。
(システム初期化後初めて Running 状態に遷移した場合は、履歴が残されていないため、Cool 状態に遷移する)
public class RunningStateMachine : StateMachine { // 親ステートマシン public ModelStateMachine Parent { get; } // エアコンモデル public AirConditioner Model { get; } // コンストラクタ public RunningStateMachine(ModelStateMachine parent) { this.Parent = parent; this.Model = parent.Model; this.ChangeToInitialState(); } // 初期状態取得 protected override State GetInitialState() { return CoolState.Instance; } }
CleanStateMachine クラス
CleanStateMachine クラスも RunningStateMachine と同様に定義します。 CleanStateMachine の初期状態は StainLevelAnalysis 状態となります。
public class CleanStateMachine : StateMachine { // 親ステートマシン public ModelStateMachine Parent { get; } // エアコンモデル public AirConditioner Model { get; } // コンストラクタ public CleanStateMachine(ModelStateMachine parent) { this.Parent = parent; this.Model = parent.Model; this.ChangeToInitialState(); } // 初期状態取得 protected override State GetInitialState() { return StainLevelAnalysisState.Instance; } }
Trigger クラス
Trigger クラスを継承した各トリガを実装します。
エアコンステートマシンでは、7 つのトリガを実装する必要があります。
名称 | 詳細 | 備考 |
---|---|---|
InitializedTrigger | 初期化完了トリガ | |
SwitchStartTrigger | スタートボタン押下トリガ | |
SwitchStopTrigger | ストップボタン押下トリガ | |
SwitchCoolTrigger | 冷房ボタン押下トリガ | |
SwitchHeatTrigger | 暖房ボタン押下トリガ | |
SwitchDryTrigger | 除湿ボタン押下トリガ | |
SwitchCleanTrigger | クリーニングボタン押下トリガ |
各トリガはシステム内で 1 つのインスタンスのみを持つべきなので、シングルトンで実装します。
また、状態遷移時にエフェクトを実行する必要がある場合は、Effect クラスを継承したエフェクトをベースクラスのコンストラクタに受け渡します。
InitializedTrigger クラス
public sealed class InitializedTrigger : Trigger { public static InitializedTrigger Instance { get; private set; } = new InitializedTrigger(); public InitializedTrigger() : base("Initialized Trigger") { } }
SwitchStartTrigger クラス
public sealed class SwitchStartTrigger : Trigger { // シングルトンインスタンス public static SwitchStartTrigger Instance { get; private set; } = new SwitchStartTrigger(); // コンストラクタ public SwitchStartTrigger() : base("Switch Start Trigger", SwitchStartEffect.Instance) { } }
SwitchStopTrigger クラス
public sealed class SwitchStopTrigger : Trigger { // シングルトンインスタンス public static SwitchStopTrigger Instance { get; private set; } = new SwitchStopTrigger(); // コンストラクタ public SwitchStopTrigger() : base("Switch Stop Trigger", SwitchStopEffect.Instance) { } }
SwitchCoolTrigger クラス
public sealed class SwitchCoolTrigger : Trigger { // シングルトンインスタンス public static SwitchCoolTrigger Instance { get; private set; } = new SwitchCoolTrigger(); // コンストラクタ public SwitchCoolTrigger() : base("Switch Cool Trigger") { } }
SwitchHeatTrigger クラス
public sealed class SwitchHeatTrigger : Trigger { // シングルトンインスタンス public static SwitchHeatTrigger Instance { get; private set; } = new SwitchHeatTrigger(); // コンストラクタ public SwitchHeatTrigger() : base("Switch Heat Trigger") { } }
SwitchDryTrigger クラス
public sealed class SwitchDryTrigger : Trigger { // シングルトンインスタンス public static SwitchDryTrigger Instance { get; private set; } = new SwitchDryTrigger(); // コンストラクタ public SwitchDryTrigger() : base("Switch Dry Trigger") { } }
SwitchCleanTrigger クラス
public sealed class SwitchCleanTrigger : Trigger { // シングルトンインスタンス public static SwitchCleanTrigger Instance { get; private set; } = new SwitchCleanTrigger(); // コンストラクタ public SwitchCleanTrigger() : base("Switch Clean Trigger") { } }
Effect クラス
Effect クラスを継承した各エフェクトを実装します。
エアコンステートマシンでは、3 つのエフェクトを実装する必要があります。
名称 | 詳細 | 備考 |
---|---|---|
SwitchStartEffect | スタートボタン押下エフェクト | |
SwitchStopEffect | ストップボタン押下エフェクト | |
CleanEndEffect | クリーニング完了エフェクト |
各エフェクトはシステム内で 1 つのインスタンスのみを持つべきなので、シングルトンで実装します。
また、ベースクラスのEffectクラスで宣言された抽象メソッドExecuteActionをオーバーライドすることで、エフェクト固有の動作を定義します。
SwitchStartEffect クラス
SwitchStartEffectクラスでは、スタートボタンが押下され、Running状態に遷移する際に行われる処理を定義します。
protected override void ExecuteAction(StateMachine context) { // 親ステートマシン(ModelStateMachine)を取得 var stm = context.GetAs<ModelStateMachine>(); // モデル(AirConditioner)を取得 var model = stm.Model; // エアコンのスタート処理を呼び出し model.Start(); }
ソース全体を示します。
public sealed class SwitchStartEffect : Effect { // シングルトンインスタンス public static SwitchStartEffect Instance { get; private set; } = new SwitchStartEffect(); // コンストラクタ public SwitchStartEffect() : base("Switch Start Effect") { } // エフェクトアクション protected override void ExecuteAction(StateMachine context) { var stm = context.GetAs<ModelStateMachine>(); var model = stm.Model; model.Start(); } }
SwitchStopEffect クラス
SwitchStoptEffectクラスでは、ストップボタンが押下され、Stop状態に遷移する際に行われる処理を定義します。
protected override void ExecuteAction(StateMachine context) { // 親ステートマシン(ModelStateMachine)を取得 var stm = context.GetAs<ModelStateMachine>(); // モデル(AirConditioner)を取得 var model = stm.Model; // エアコンの停止処理を呼び出し model.Stop(); }
ソース全体を示します。
public sealed class SwitchStopEffect : Effect { // シングルトンインスタンス public static SwitchStopEffect Instance { get; private set; } = new SwitchStopEffect(); // コンストラクタ public SwitchStopEffect() : base("Switch Stop Effect") { } // エフェクトアクション protected override void ExecuteAction(StateMachine context) { var stm = context.GetAs<ModelStateMachine>(); var model = stm.Model; model.Stop(); } }
CleanEndEffect クラス
CleanEndEffectでは、クリーニング処理が完了し、Running状態に遷移する際に行われる処理を定義します。
// エフェクトアクション protected override void ExecuteAction(StateMachine context) { // 親ステートマシン(ModelStateMachine)を取得 var stm = context.GetAs<ModelStateMachine>(); // モデル(AirConditioner)を取得 var model = stm.Model; // エアコンのクリーニング完了処理を呼び出し model.CleanEnd(); }
ソース全体を示します。
public sealed class CleanEndEffect : Effect { // シングルトンインスタンス public static CleanEndEffect Instance { get; private set; } = new CleanEndEffect(); // コンストラクタ public CleanEndEffect() : base("Clean End Effect") { } // エフェクトアクション protected override void ExecuteAction(StateMachine context) { var stm = context.GetAs<ModelStateMachine>(); var model = stm.Model; model.CleanEnd(); } }
次回予告
次回も引き続きステートマシンの実装を行っていきます。