diff --git a/Program.cs b/Program.cs
index b54d3bb..450c50d 100644
--- a/Program.cs
+++ b/Program.cs
@@ -20,6 +20,7 @@ using design_patterns.behavioral.iterator;
using design_patterns.behavioral.mediator;
using design_patterns.behavioral.memento;
using design_patterns.behavioral.observer;
+using design_patterns.behavioral.state;
namespace design_patterns
{
@@ -53,7 +54,8 @@ namespace design_patterns
// await IteratorSample.Run();
// await MediatorSample.Run();
// await MementoSample.Run();
- await ObserverSample.Run();
+ // await ObserverSample.Run();
+ await StateSample.Run();
}
catch (System.Exception ex)
{
diff --git a/behavioral/state/StateSample.cs b/behavioral/state/StateSample.cs
new file mode 100644
index 0000000..e2cc03d
--- /dev/null
+++ b/behavioral/state/StateSample.cs
@@ -0,0 +1,128 @@
+using System;
+using System.Threading.Tasks;
+using Stateless;
+
+namespace design_patterns.behavioral.state
+{
+ ///
+ /// State is a behavioral design pattern that lets an object
+ /// alter its behavior when its internal state changes.
+ /// It appears as if the object changed its class.
+ ///
+ /// Use it when:
+ /// - you have an object that behaves differently depending
+ /// on its current state, the number of states is enormous,
+ /// and the state-specific code changes frequently.
+ /// - you have a class polluted with massive conditionals
+ /// that alter how the class behaves according to the current values
+ /// of the class’s fields.
+ /// - you have a lot of duplicate code across similar states
+ /// and transitions of a condition-based state machine.
+ ///
+ /// easy to use STATELESS nuget package
+ /// https://www.nuget.org/packages/stateless
+ /// https://github.com/dotnet-state-machine/stateless
+ ///
+ public class StateSample
+ {
+ public static async Task Run()
+ {
+ Console.WriteLine("Behavioral - State");
+
+ var machineOrder = BuildMachine();
+
+ var trigger =OrderTrigger.CreateOrder;
+ machineOrder.Fire(trigger);
+ System.Console.WriteLine($"state: {machineOrder.State}");
+ if(machineOrder.State != OrderState.New)
+ System.Console.WriteLine($"Error with order state trigger {trigger} - state {machineOrder.State}");
+
+ trigger =OrderTrigger.RegisterOrder;
+ machineOrder.Fire(trigger);
+ System.Console.WriteLine($"state: {machineOrder.State}");
+ if(machineOrder.State != OrderState.Registered)
+ System.Console.WriteLine($"Error with order state trigger {trigger} - state {machineOrder.State}");
+
+
+ // // once cancelled it cannot migrate to other sates
+ // trigger = OrderTrigger.CancellByCustomer;
+ // machineOrder.Fire(trigger);
+ // System.Console.WriteLine($"state: {machineOrder.State}");
+
+ trigger = OrderTrigger.BeginProcessing;
+ machineOrder.Fire(trigger);
+ System.Console.WriteLine($"state: {machineOrder.State}");
+
+ trigger = OrderTrigger.Packaging;
+ machineOrder.Fire(trigger);
+ System.Console.WriteLine($"state: {machineOrder.State}");
+
+ trigger = OrderTrigger.Shipping;
+ machineOrder.Fire(trigger);
+ System.Console.WriteLine($"state: {machineOrder.State}");
+
+ trigger = OrderTrigger.Delivering; // or .ReturnByCustomer or .ReturnByShipment
+ machineOrder.Fire(trigger);
+ System.Console.WriteLine($"state: {machineOrder.State}");
+ }
+
+ public static StateMachine BuildMachine() {
+ var machineOrder = new StateMachine(OrderState.New);
+ // from new to draft
+ machineOrder.Configure(OrderState.New)
+ .PermitReentry(OrderTrigger.CreateOrder)
+ .Permit(OrderTrigger.SaveAsDraft, OrderState.Draft)
+ .Permit(OrderTrigger.RegisterOrder, OrderState.Registered);
+
+ // from draft to registered
+ machineOrder.Configure(OrderState.Draft)
+ .Permit(OrderTrigger.RegisterOrder, OrderState.Registered);
+ // from registered to cancelled or begin processing
+ machineOrder.Configure(OrderState.Registered)
+ .Permit(OrderTrigger.CancellByCustomer, OrderState.Cancelled)
+ .Permit(OrderTrigger.BeginProcessing, OrderState.Processing);
+ // from processing to cancelled of packaging
+ machineOrder.Configure(OrderState.Processing)
+ .Permit(OrderTrigger.CancellBySupplier, OrderState.Cancelled)
+ .Permit(OrderTrigger.Packaging, OrderState.Packaged);
+ // from packaged to shipped or return
+ machineOrder.Configure(OrderState.Packaged)
+ .Permit(OrderTrigger.Shipping, OrderState.Shipped)
+ .Permit(OrderTrigger.ReturnByShipment, OrderState.ReturnedByShipment);
+ // from shipped to
+ machineOrder.Configure(OrderState.Shipped)
+ .Permit(OrderTrigger.Delivering, OrderState.Completed)
+ .Permit(OrderTrigger.ReturnByShipment, OrderState.ReturnedByShipment)
+ .Permit(OrderTrigger.ReturnByCustomer, OrderState.ReturnedByCustomer);
+ return machineOrder;
+ }
+
+ public enum OrderState {
+ New,
+ Draft,
+ Registered,
+ Processing,
+ Packaged,
+ Shipped,
+ Completed,
+ // other states
+ Cancelled,
+ ReturnedByShipment,
+ ReturnedByCustomer
+ }
+
+ public enum OrderTrigger {
+ CreateOrder,
+ SaveAsDraft,
+ RegisterOrder,
+ CancellByCustomer,
+ CancellBySupplier,
+ BeginProcessing,
+ Packaging,
+ Shipping,
+ Delivering,
+ ReturnByShipment,
+ ReturnByCustomer
+ }
+ }
+}
\ No newline at end of file
diff --git a/design_patterns.csproj b/design_patterns.csproj
index 1d2d39a..91f04cb 100644
--- a/design_patterns.csproj
+++ b/design_patterns.csproj
@@ -5,4 +5,8 @@
net5.0
+
+
+
+