0

I am currently making a courier service webpage - a customer can give up an order - the order's state can be changed by a courier (new, accepted, inDelivery, delivered, canceled). I am using the state design pattern to depict this, as it made the most sense to me.

I would like to save all the orders in a relational database (I am using H2 and Hibernate/JPA) - but I can't figure out how to get the state back when loading the object.

Two methods come to mind:

  1. Create a table for every single state and save the object in the table corresponding to its state (I can't find out how (if it's even possible) to realize that).
  2. Give the order class an attribute which corresponds to the state it's in - and then set the internal state of the object equal to the relevant state when loading the object again. But wouldn't that destroy the purpose of the state design pattern? Isn't the target to minimize if/else-statements and switch-walls?

What should I do? Is there a better way to solve this?

jaco0646
  • 15,303
  • 7
  • 59
  • 83
Denny
  • 27
  • 6
  • Does this answer your question? [How to persist objects which implement the State pattern?](https://stackoverflow.com/questions/23780426/how-to-persist-objects-which-implement-the-state-pattern) – jaco0646 Nov 23 '21 at 15:11

3 Answers3

0

I would create an entity Delivery and an entity State, where State would have new, accepted, inDelivery, delivered and canceled as its entries/rows.

So you would have an DeliveryEntity that gets stored in the delivery table as row. The same applies for the State in the state table, but here you only have a fixed set of entries/rows representing your states. Because each row has a Primary Key you can reference your State in your Delivery by it as foreign key.

sschrass
  • 7,014
  • 6
  • 43
  • 62
0

That very much depends on your use case.

Do you plan to have thousands of millions of rows? Then having a table per state actually makes sense. It's called partitioning, and usually, your application won't know that you have set of tables. But your database will. I'll assume this is not the case.

Second option is sound, if it's a toy project. The goal of State design pattern is not to reduce number of if/else statements. It will usually produce more if/else statements, from my experience. The goal is to encapsulate state transition. That is, with if/elses all around your code, it's very easy to move your Order from Created to Completed state without it actually being processes. State design pattern helps resolve that.

But there's actually a third option, which is usually used by real-life system. Have OrderStates table which will save all states the order had been at. Create a row each time order moves between states. That will allow you to actually understand what happens in your system.

Alexey Soshin
  • 16,718
  • 2
  • 31
  • 40
0

Your states are just subclasses of OrderState, right? If you save the state name as an attribute of an order such that it is the name of the subclass to instantiate, you could use Java reflection API to instantiate it on loading. Follow the pattern (idiom) of a simple factory with reflection.

Assuming your state names and classes are the same, with some kind of convention, e.g., OrderStateNew, OrderStateAccepted, etc.:

name = /* some field from the order ... */;
Class c = Class.forName("com.denny.orders." + name);    
OrderState state = (OrderState)c.newInstance();

You'd need to make sure the new() runs properly (hopefully your state objects are not too complicated to initialize, since that's messier in reflection).

Personally, I'm not a big fan of the State pattern because of stuff like this (even though this code looks simple, it's not - you need to sanitize the name and test all the cases). Sometimes if/then logic is not so bad (its complexity is more explicit?). You can also avoid if/then logic with look-up tables (state machines worked on computers that way long before polymorphic methods and OO).

Fuhrmanator
  • 11,459
  • 6
  • 62
  • 111
  • Isn't the Memento Pattern specifically intended for persisting object state? Would that not be the classic solution here? – jaco0646 Aug 06 '18 at 22:55
  • @jaco0646 Memento could be used, but it's a simple problem to reconstitute an order's state. – Fuhrmanator Aug 06 '18 at 23:10