Re: Correct use of State Pattern
- From: "Oliver Wong" <owong@xxxxxxxxxxxxxx>
- Date: Fri, 24 Mar 2006 17:11:10 GMT
"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
.
- Follow-Ups:
- Re: Correct use of State Pattern
- From: Roedy Green
- Re: Correct use of State Pattern
- References:
- Correct use of State Pattern
- From: mdjj
- Correct use of State Pattern
- Prev by Date: Java MIDI message problem
- Next by Date: Re: Correct use of State Pattern
- Previous by thread: Re: Correct use of State Pattern
- Next by thread: Re: Correct use of State Pattern
- Index(es):
Relevant Pages
|