Re: Correct use of State Pattern



"mdjj" <m_d_j_j@xxxxxxxxxxxxx> wrote in message news:1143217743.379456.21340@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
I want to know if this is a suitable use of the state pattern.

I have a business object that moves between various states during it's
lifecycle.
The actions you can do to the object at each state are not necessarily
identical.
All you can really do is save the object to a persistent store and move
it to the
next state. To move it to the next state you have to have filled in
certain data
that needs to be validated before allowing you to move on.

All the examples i've seen re the State Pattern have similar methods
applying at each
state but the method behaves differently. Potentially I have a Save,
Validate and MoveToNextState methods.

Does my scenario fit the State Pattern or am I trying to fit a square
peg into a round hole?
If it doesn't is their an alternative pattern I should be looking at?

If it does, I was planning on writing seperate State classes but where
do I put my validation?
The validation applies to the business object but is different
depending on what state the BO
is in, therefore it seems sensible to put it in each state class?


If my understanding is correct, you are saying that at each state, a different set of operations are applicable to the business object. Unless you want to use reflection, you will probably need to have a different interface (or class) for each state.

As a concrete example, let's say the states are egg -> tadpole -> frog, and the methods differ consireably from one state to another; e.g. becomeImpregnated(), hatch(), swim(), eatAlgae(), metamorphose(), hop(), eatInsects(). The methods should be more or less called in the presented order, but there may be some slight variantions.

<pseudoCode>
public interface Egg {
public void becomeImpregnated();
public Tadpole hatch();
}

public interface Tadpole {
public void swim();
public void eatAlgae();
public Frog metamorphose();
}

public interface Frog {
public void hop();
public void eatInsects();
}
</pseudoCode>

You could have the same class implement all 3 interfaces, or you could have a class for each interface.

<pseudoCode>
public class EggImpl implements Egg {
private impregnated = false;
/*package protected*/ String dna;

public EggImpl() {
dna = someRandomSequence();
}

public void becomeImpregnated() {
this.impregnated = true;
dna.modifySomehow();
}

public Tadpole hatch() {
if (!this.impgrenated) {
return null;
}
return new Tadpole(this);
}
}

public class TadpoleImpl implements Tadpole {
/*package protected*/ String dna;
/*package protected*/ Object nutrition;

TadpoleImpl(Egg e) {
/*Package protected constructor*/
this.dna = e.dna;
}

boolean swam = false;
boolean ate = false;

public void swim() {
this.swam = true;
}

public void eatAlgae() {
if (this.swam = true) {
nutrition.modifySomehow()
this.ate = true;
this.swam = false;
}
}

public Frog metamorphose() {
if (!this.ate) {
return null;
}
return new FrogImpl(this);
}
}

etc.
</pseudoCode>

The "3 different classes" approach has each state acting as a factory for the next state.

<pseudoCode>
public EggTadpoleFrog implements Egg, Tadpole, Frog {
public Tadpole hatch() {
return this;
}

public Frog metamorphose() {
return this;
}

/*Rest of the code is similar to the above*/
}
</pseudoCode>

With 1 class, you're just "re-casting" the object, instead of creating a new object each time.

By using interfaces, instead of concrete classes, you're free to switch between these two implementations without affecting the client.

- Oliver

.



Relevant Pages

  • Re: Speed of interfaces vs inheritance
    ... implementation of an interface. ... Another thing to note is the degree of actual polymorphism at the call site. ... But that kind of optimisation makes considering call sites difficult. ... abstract public void abstractCall; ...
    (comp.lang.java.programmer)
  • Re: HashMap get/put
    ... interface IFace ... public void DoitNow() ... DoitNow is generated as a non-virtual method. ... But, change DoitNowto be virtual, add an override in Derived, and then rebuild Assembly1.dll. ...
    (comp.lang.java.programmer)
  • Re: pls clarify important concepts...
    ... >>methods in that interface.. ... > public class MyClass implements MyInterface { ... > public void myMethod() { ... > public class UserDaoJDBC implements UserDao { ...
    (comp.lang.java.help)
  • Re: Looking for a way to avoid use of instanceOf
    ... on the front of an interface name. ... unless there's an ordering on constraints. ... public void handle; ... You then add a method to RegulatedNME: ...
    (comp.lang.java.programmer)