I am new to the State design pattern and I can't find a proper example of saving different states of an object to the database (SQL Server in my case). The scenario is quite similar [almost identical] to the example described in the following article, however I have not found an applicable solution for persisting the states to the database. Can you guys recommend a link or possiblly give an example?
State Pattern Usage and Sample in C#
In addition: How do you enumerate all different ConcreteState types at run time? For instance, if you have 10 different states, do you declare an EnumStates with 10 different members and give every single ConcreteState member an associated EnumStates member, or you do get all the distinct states by getting the subclasses of ConcreteState?
For you information, I need to be able to search for entities based on their different states.
The state pattern is used in computer programming to encapsulate varying behavior for the same object, based on its internal state. This can be a cleaner way for an object to change its behavior at runtime without resorting to conditional statements and thus improve maintainability.
Applicability. Use the State pattern in either of the following cases: An object's behavior depends on its state, and it must change its behavior at run-time depending on that state. Operations have large, multipart conditional statements that depend on the object's state.
State design pattern is used when an Object changes its behavior based on its internal state. If we have to change behavior of an object based on its state, we can have a state variable in the Object and use if-else condition block to perform different actions based on the state.
State design pattern is one of the behavioral design pattern. State design pattern is used when an Object change its behavior based on its internal state.
I didn't like the example you linked, below I listed the reasons:
I would go for this pattern instead:
pattern infrastructure
public interface IStateObject<T>
{
T State { get; set; }
void Process();
}
Example implementation for some pseudo Order object
public enum OrderState
{
Taken,
Approved,
Payed,
Emailed,
BeforeShipment
//etc.. etc..
}
public class Order : IStateObject<OrderStates>
{
//some linear fields of order..
//: name, description, etc.. etc..
public OrderStates State { get; set; }
public void Process()
{
switch (State)
{
case OrderState.Taken:
// code to handle this state
break;
case OrderState.Approved:
// etc..
break;
}
//persist myself to db.
}
}
It is very simple as you can save object per type per context of the object in one row.
Also an object is created once as intuitively it should have if we had no computer nears us..
But mostly because it is very straight forward and very flexible.
You might notice you actually may not need the IStateObject<T>
at all - but I would argue you will need it later on when you want to process on vertical decisions.
keep in mind that T
doesn't have to be an enum. it could serve as common ground to evolve according to your app needs.
To further point out the mess I mentioned in the beginning of this answer,
Let's say we want to have history to previous states of the order:
Using the pattern offered in this answer - you add a PreviousOrderState property and now you have history per row.. And there are other ways I'm sure you can think of..
But using the "State Pattern" - you will be in serious problem... it will actually going to be complicated by a full "scale level" to do that.. you will have to be able to link from each type of table to each type of other table - or try to force Object Oriented on your database...
See my point? the States pattern is simply not designed for data centric apps.
Good Luck.
Don't try to translate the states into columns in a table, that wont work.
Instead serialize the states using JSON.NET as it supports inheritance. Then store it in a table like:
create table OrderStates
(
OrderId int not null,
Data nvarchar(MAX) not null
);
Include more columns if you want but only columns which is required to identify what the states are used for.
To activate the inheritance support in JSON.NET you have to use:
var json = JsonConvert.SerializeObject(yourState, typeof(StateBaseClass), JsonConvert.DefaultSettings)`.
using (var cmd = sqlConnection.CreateCommand())
{
cmd.CommandText = "INSERT INTO OrderStates (OrderId, Data) VALUES(@OrderId, @Data)";
cmd.Parameters.AddWithValue("OrderId", orderId);
cmd.Parameters.AddWithValue("Data", json);
cmd.ExecuteNonQuery();
}
Same goes when deserializing, specify the base class when using JsonConvert.DeserializeObject()
.
How do you enumerate all different ConcreteState types at run time? For instance, if you have 10 different states, do you declare an EnumStates with 10 different members and give every single ConcreteState member an associated EnumStates member, or you do get all the distinct states by getting the subclasses of ConcreteState?
Subclasses. It's the only way to be able to introduce new states or remove old ones without having to modify the other classes. Each modification of existing classes can introduce bugs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With