Decoupling States using the State Pattern - java

I am unsure as to what the best OO design approach should be regarding a particular State pattern I am implementing. Please consider the following:
public class World {
private Animal dog_;
private Animals cats_;
…..
public void sendDogRequest(DogRequest request) {
dog_.sendRequest(request);
}
…
public Cat getCat(String catName) {
…
return cat;
}
...
}
public class Animal<RequestType extends Request, StateType extends State> {
private State<StateType> currentState_;
….
public void sendRequest(RequestType request) {
request.sendToState(currentState_);
}
public void setState(StateType state) {
currentState_ = state;
}
}
public class Dog extends Animal<DogState> {
…
}
public class DogState extends State {
public DogState(Dog dog) {
…
}
public void seeCat(Cat cat) { }
}
public class OnLeashState extends DogState {
public void seeCat(Cat cat) {
dog.setState(new BarkingState());
}
}
public class OffLeashState extends DogState {
public void seeCat(Cat cat) {
dog.setState(new ChasingAfterAnimalState(cat));
cat.sendRequest(new RunAwayRequest(cat));
}
}
public interface Request<StateType extends State> {
public void sendToState(StateType state);
}
public class DogRequest extends Request<DogState> { }
public class SeeCatRequest extends DogRequest {
private Cat cat_;
public SeeCatRequest(Cat cat) {
cat_ = cat;
}
public void sendToState(DogState state) {
state.seeCat(state);
}
}
public class Controller() {
public Controller(World model, View view) {
…
}
...
public void catSelected(String catName) {
Cat cat = world.getCat(catName);
Dog dog = world.getDog();
world.sendDogRequest(new SeeCatRequest(cat));
}
…
}
My area of hesitation is with the usages of the word new here, ie. instantiating a new SomeState() with another State, or new SomeRequest() within the Controller or another State. It seems to me that this would produce high coupling between the States and their siblings, as well as the Controller and States.
The requirements are as follows:
It MUST be possible to add new States, for example adding a SniffingState.
It also MUST be possible to replace existing States with new ones. For example, I should be able to replace OffLeachState with a different OffLeashState that performs a different action. For example (for some reason the code won't format):
public class OffLeachState2 extends DogState {
public void seeCat(Cat cat) {
if (dog.knows(cat)) {
// dog changes to "PlayWithCatState"
// cat gets a "PlayWithDog" request
} else {
// dog changes to "ChaseAnimalState"
}
}
}
Finally, all changes within the World class MUST be logged. That means that the World class has a logger which is keeping track of everything that is going on. This is also because the World class is a model, and has to fire off a notifyObservers() so that the view knows to do something.
My question is, where should the states, requests etc be stored? For example:
Should there be state "getters" in Dog? for example, dog.getBarkingState(), dog.getOnLeashState(), etc? This seems to make sense, but it doesn't make the Dog class resistant to change. Ie, every time I add a new DogState class, I also have to make sure that Dog has a getter for it. Also, the World doesn't know about these changes, so it doesn't log them nor notify observers.
Should there be a class called DogStates and I can run DogStates.getBarkingState()? Again, similar problems to the one above.
Should they be a part of the World class? For example, world.setDogState(dog, world.getDogBarkingState()? This would solve the logging/updating problem, but puts too much responsibility on the World class.
Should it be some combination thereof, for example world.setState(dog, dog.getBarkingState()? This COULD be good, but doesn't assure type safety. For example, I could pass in a Dog object with a CatState, and it wouldn't know the difference.
Solution #4 seems the best to me, but I would like some other opinions about this issue.
The same question applies to the Request object. I originally wanted to send Requests by Strings which were associated with an object, for example world.sendRequest(dog, DogRequests.SEE_CAT), but then I couldn't pass the cat object as an argument.
Thank you very much for your time!

1.) This looks like a programming exam question. In such scenarios, if unsure what to do, use a Pattern! So every State should be generated by a StateFactory and give the Factory instance some information about the World so it can decide which specific State instance to create.
Here's the logging stuff:
public class World implements StateChangeListener {
private Animal dog_;
private Animals cats_;
private final List<StateChangeListener> listeners = new ArrayList<StateChangeListener>();
public World() {
listeners.add(this);
}
// Instead of sending DogRequests to Dogs via the sendDogRequest method:
public <RequestType extends Request> void sendRequest(
Animal<RequestType, ?> animal, Request<RequestType> request) {
animal.sendRequest(request);
for(StateChangeListener listener : listeners) {
listener.stateChanged(animal, request);
}
}
public void stateChanged(Animal<?, ?> animal, State<?> state) {
// ... log here ...
}
...
And that Factory stuff (probably a bit scatterbrained, Generics might not work correctly ;o).
public enum LocationEnum {
HOME, PARK, POND, FOREST
}
public interface StateFactory<StateType extends State> {
State<StateType> create(Animal<StateType, ?> animal, Context context);
}
// Do stuff Dogs do.
public class DogStateFactory<DogState> {
public State<DogState> create(Animal<DogState, ?>, Context context) {
if(context.currentAnimalLocation==LocationEnum.POND) {
return new IgnoreEverythingState();
}else if(context.currentAnimalLocation==LocationEnum.HOME){
return new PerpetualBarkState();
}else {
return new FollowEveryCatState();
}
}
}
public class Animal<RequestType extends Request, StateType extends State> {
private StateFactory<StateType> stateFactory;
private State<StateType> currentState_;
public void sendRequest(Request<RequestType> request) {
request.sendToState(currentState_);
}
// A specific animal knows what it wants to do, depending on it's current
// state and it's situational context. We don't want other animals
// to set the state for us.
public void determineState() {
currentState_ = stateFactory.create(this, new Context(...));
// One might want to extend the messaging stuff in a way that
// the World instance can log this state change.
}
}
public class Dog extends Animal<DogRequest, DogState> {
public Dog() {
this.stateFactory = new DogStateFactory<DogState>();
}
}
2.) If you want the World to know everything happening in it, you could substitute the state setters whith messages and let the World instance listen to everybody's state changes.

Related

Is it okay for a class method to reflect a passive action on the object, or must it always reflect active action?

I was wondering about the proper way to write class methods. I am pretty sure that my first class here follows proper coding standards because the methods reflect things that an instance of the class might do.
class Turkey {
public void hunt() {
System.out.println("Hunting for insects...");
}
public void eat() {
System.out.println("Eating plants, fruits, berries and insects...");
}
}
However, would it be okay for a class method to reflect an action of which the class instance is a recipient instead?
class Turkey {
public void hunt() {
System.out.println("Hunting turkey...");
}
public void eat() {
System.out.println("Happy Thanksgiving!");
}
}

What kind of relationship does an interface have with it implementing class?

A subclass has a relationship that is described as IS-A with it base class, but a base class does not share this kind of relationship with it subclass. I was wandering what kind of relationship an interface have with it implementing class since an object of that class can be passed to interface object and the interface object can only access methods defined it concrete Interface.
public class main {
public static void main(String[]args){
Nigeria ng = new Nigeria(){};
//Interface object can accept Nigerias object which is not posible in Inheritance
Continent continent = ng;
//prints Country is in Africa
continent.Africa();
//continent.language(); will not compile language is not in the interface
//Print Democratic thought this should print Undefined since it is inialied with default.
continent.Goverment();
}
}
interface Continent{
public void Africa();
default void Goverment(){
System.out.println("Undefined");
}
}
class Nigeria implements Continent{
#Override
public void Africa(){
System.out.println("Country is in Africa");
}
public void language(){
System.out.println("Official Language is English");
}
public void Goverment(){
System.out.println("Democratic");
}
}
If you are looking for English-language analogues, an Interface is not an "Is a..." nor "Has a..." relationship, but more an "Is...".
An Interface is not about the class that uses it.
It's about the consumer that asks for it.
If you wanted to see it as anything, you could see it as an adjective.
"He is Responsible".
Well, what does he do?
He finishes tasks; he takes ownership of his mistakes; he makes them right.
Is he a pilot, is he a surgeon, is he a doctor?
Is he a child, a father, a greatGrandfather?
Do you care?
I need a responsible person, to help me do this job.
Does ResponsiblePerson inherit from PoliceOfficer? Does Lawyer inherit from ResponsiblePerson, because I'm sure there can be irresponsible lawyers.
class Lawyer extends Person { }
class ResponsibleLawyer extends Lawyer implements ResponsibleEntity { }
class NeedyPerson extends Person {
public void acceptHelp (ResponsibleEntity somebody) {
try {
somebody.attemptTask( someTask );
} catch (TaskCompletionError err) {
somebody.takeOwnership(err);
somebody.fixMistake(err);
}
}
}
Can corporations be Responsible too?
Perhaps we don't see it too often, but it's theoretically possible:
class LawFirm extends CorporateEntity { }
class BetterLawFirm extends LawFirm implements ResponsibleEntity { }
Can somebody be a responsible corporate body? Well, so long as that corporate body does all of the same things that the responsible person would otherwise do, sure.
In another example, you might have a Switchable interface.
Looking at that name, you could surmise that the thing you're being given has a switch which can be poked.
So what methods might it have?
on( )
off( )
toggle( )
isOn( )
sounds like a useful set to have.
What benefit is there to having an interface like this?
Well, now I know that I can deal with a switch, and its lineage doesn't matter.
If all I want is a class which takes a switch and does something with it, why do I need to create dozens of classes, just to accept my dozens of things with switches?
Or override methods into the dirt to do the same.
class SwitchThrower {
public void throwSwitch (CoffeeMaker coffeeMaker) { coffeeMaker.on(); }
public void throwSwitch (LightSwitch lightSwitch) { lightSwitch.on(); }
public void throwSwitch (GhostTrap ghostTrap) { ghostTrap.on(); }
public void throwSwitch (TheHeat theHeat) { theHeat.on(); }
public void throwSwitch (CarIgnition ignition) { ignition.on(); }
}
...
why not just:
class SwitchThrower {
public void throwSwitch (Switchable switch) { switch.on(); }
}
class LightSwitch implements Switchable {
private boolean currentlyOn;
public LightSwitch (boolean initiallyOn) {
currentlyOn = initiallyOn;
}
public LightSwitch () {
currentlyOn = false;
}
public boolean on () {
currentlyOn = true;
return currentlyOn;
}
public boolean off () {
currentlyOn = false;
return currentlyOn;
}
public boolean toggle (boolean forceOn) {
boolean state;
if (forceOn == true) {
state = on();
} else {
state = off();
}
return state;
}
public boolean toggle () {
boolean state;
if (isOn() == true) {
state = off();
} else {
state = on();
}
return state;
}
public boolean isOn () {
return currentlyOn;
}
}
...et cetera
As you can see, aside from describing a basic feature-set of the implementer, interfaces are not about the class at all, but rather the consumer.
An even more awesome implementation of this, in different languages, is _Traits_.
Traits are typically like Interfaces, but they have default behaviour associated with them.
Looking at my Switchable and my LightSwitch, you could imagine that practically all classes with this switch would have the same methods, with the same method behaviour...
...so why would I rewrite all of those methods over again, if I'm already going through the trouble of defining the signature in the interface?
Why couldn't I just add default behaviour in there, and have it apply to the implementer, unless a method is overridden?
Well, that's what Traits / Mix-Ins allow.
The relationship is only the "contract" that the class is getting to implement the methods the interface is offering.
That is how java can separate WHAT objects can do (Interface) and HOW the inherited class will do it.

How to apply more constraints on an interface declaration in Java?

Let's say I have following interface:
interface Mammal {
void marry(Mammal m);
Mammal giveBirthTo();
}
However, this doesn't say quite exactly what I want.
Obviously, a human can't marry a dog, nor give birth to a cat. So how can I embed this information into the interface, such that the input type and output type can be changed automatically as it gets implemented?
You could use generics and change your design.
Something in the lines of:
interface Marriable<T extends Mammal> {
void marry(T sweetHalf);
T giveBirthTo();
}
... where Mammal is your top interface or abstract class, and Human, Dog, Unicorn etc. extend / implement it.
You can generify your interface using a recursive type variable:
interface Mammal<T extends Mammal<T>> {
void marry(T m);
T giveBirthTo();
}
This way, the Java compiler can give you a certain validation level. Notice however that this approach is still open to abuse. For example:
class Cat implements Mammal<Cat> {
#Override void marry(Cat cat) { ... }
#Override Cat giveBirthTo() { ... }
}
class Dog implements Mammal<Cat> { // implements wrong interface
#Override void marry(Cat cat) { ... }
#Override Cat giveBirthTo() { ... }
}
The compiler can only assure that you implement the Mammal interface by some sub type of the same interface, but not by the particular class that implements it. This latter type constraint cannot be expressed in the Java programming language.
Generics. Try with
private static interface Race {
}
private static class Human implements Race {}
private static class Canine implements Race {}
private static interface Being<R extends Race> {
void marry(Being<R> other);
Being<R> giveBirthTo();
}
private void tryMe() {
Being<Human> aHuman = new Being<Human>() {
#Override
public void marry(Being<Human> other) {
}
#Override
public Being<Human> giveBirthTo() {
return null;
}
};
Being<Canine> aCanine = new Being<Canine>() {
#Override
public void marry(Being<Canine> other) {
}
#Override
public Being<Canine> giveBirthTo() {
return null;
}
};
aHuman.marry(aCanine); // not possible
}

Using Generalization properly

Suppose you have the following Interfaces
public interface Action {
public State execute(State state);
}
public interface State {
public Collection<Action> getPossibleActions();
}
And this method
public static Collection<State> getAllSuccessorStates(State state){
Collection<State> allSuccessors = new HashSet<>();
for (Action action: state.getPossibleActions()){
State successorState = action.execute(state);
allSuccessors.add(successorState);
allSuccessors.addAll(getAllSuccessorStates(successorState));
}
return allSuccessors;
}
A Concrete State could be for example a Chessboard and an Action the movement of a Piece on the board. Obviously the Chess-Actions need to know the concrete State class:
public class ChessAction implements Action {
#Override
public ChessState execute(ChessState state) {...}
}
Which is ofcourse not an allowed way of overriding execute. What would be the correct way of implementing this, so you can have concrete Actions, that operate on concrete States, which you can give as Arguments to getAllSuccessorStates?
I thought about Generics and also got answers pointing to Generics, but that brings about new Problems. If i write the Action class like this:
public interface Action<E extends State> {
public E execute(E state);
}
i will have the following Problem with ChessState class:
#Override
public Collection<Action<State>> getPossibleActions() {
Collection<Action<State>> actions = new ArrayList<>();
actions.add(new ChessAction());
return actions;
}
the line Actions.add causes the following error: The method add(Action) in the type Collection> is not applicable for the arguments (ChessAction)
Now i could declare Actions as
Collection<Action<ChessState>> actions = new ArrayList<>();
but that wont be a permitted return type.
You can use generics (needs java 1.5 or above):
public interface Action<T extends State> {
public T execute(T state);
}
public class ChessAction implements Action<ChessState> {
#Override
public ChessState execute(ChessState state) {...}
}
Hope that helps.
i found a satisfactory Solution now, which works correctly, doesnt need instanceof and yields no compile warnings:
public interface Action<E extends State<?>> {
public E execute(E state);
}
public interface State<E extends Action<?>> {
public Collection<E> getPossibleActions();
}
public static <A extends Action<S>, S extends State<A>> Collection<S> getAllSuccessorStates(S state){
Collection<S> allSuccessors = new HashSet<>();
for (A localAction: state.getPossibleActions()){
S successorState = localAction.execute(state);
allSuccessors.add(successorState);
allSuccessors.addAll(getAllSuccessorStates(successorState));
}
return allSuccessors;
}
Example of using getAllSuccessorStates (i forgo the implementation Details of the concrete classes here, but the Point should be apparent. You can use the method getAllSuccessorStates with any concrete State class, get Instances of this class in return collection and use them)
public class TestState implements State<TestAction> {...}
public class TestAction implements Action<TestState> {...}
public static void main(String[] args) {
TestState initialState = new TestState("1");
Collection<TestState> allSuccessorStates = getAllSuccessorStates(initialState);
for (TestState state: allSuccessorStates){
System.out.println(state.getStateStr());
}
}
This Question arose from the book "AI-A modern approache" by Stuart Russel and Peter Norvig, in case somebody who reads this book has the same Problem and searches for solutions. In the book the Action and State methods are inside a Problem Class, but i think in this way the OO-design is better.
Well, ChessState must have the same signature of execute as in the Action interface. If you require that ChessAction.execute accept only ChessState, you can write :
public class ChessAction implements Action {
#Override
public State execute(State state)
{
if (!(state instanceof ChessState))
throw new SomeException ();
ChessState cs = (ChessState) state;
...
}
}
You need to implement the same inherited method, and it will work since State is a super class for CheesState.
public class ChessAction implements Action {
#Override
public State execute(State state) {...}
}
Inside the execute method, you can use polymorph method (define in State and redefined ChessState), or you can cast to ChessState (ChessState s = (ChessState) state;), then use it as you need

Why do we start Visitor by calling Acceptor.accept(), and not Visitor.visit()?

In Wikipedia sample and in GoF book, usage of Visitor pattern is started by calling accept method on some acceptor. But why is it this way? Why can't we start calling visit method with desired acceptor as an argument? We can still make visitor behavior depend on 2 types -- of visitor and of acceptor (double dispatch) -- and we can eliminate redundant call (as it seems to me).
Here's sample code to illustrate this:
public interface Visitor {
void visit(AcceptorA acceptor);
void visit(AcceptorB acceptor);
}
//
// Visitor which sings
//
class SingingVisitor implements Visitor {
public void visit(AcceptorA acceptor) {
System.out.println("sing A");
}
public void visit(AcceptorB acceptor) {
System.out.println("sing B");
}
}
//
// Visitor which talks
//
class TalkingVisitor implements Visitor {
public void visit(AcceptorA acceptor) {
System.out.println("talk A");
}
public void visit(AcceptorB acceptor) {
System.out.println("talk B");
}
}
//
// Acceptor subclasses
//
class AcceptorA implements BaseAcceptor {
}
class AcceptorB implements BaseAcceptor {
}
//
// Launcher class
//
class VisitorMain {
public static void main(String[] args) {
Visitor v = new TalkingVisitor();
AcceptorA a = new AcceptorA();
AcceptorB b = new AcceptorB();
v.visit(a);
v.visit(b);
v = new SingingVisitor();
v.visit(a);
v.visit(b);
}
}
Consider:
class House implements HouseAcceptor {
HouseAcceptor kitchen;
HouseAcceptor livingRoom;
void accept(HouseVisitor visitor) {
visitor.visit(this);
kitchen.accept(visitor);
livingRoom.accept(visitor);
}
}
class Kitchen implements HouseAcceptor {
void accept(HouseVisitor visitor) {
visitor.visit(this);
}
}
class LivingRoom implements HouseAcceptor {
void accept(HouseVisitor visitor) {
visitor.visit(this);
}
}
class SpeakingHouseVisitor implements HouseVisitor {
void visit(HouseAcceptor acceptor) {
System.out.println("Inside a HouseAcceptor");
}
void visit(House acceptor) {
System.out.println("Inside a House");
}
void visit(Kitchen acceptor) {
System.out.println("Inside a Kitchen");
}
void visit(LivingRoom acceptor) {
System.out.println("Inside a LivingRoom");
}
}
...
HouseAcceptor acceptor = new House();
HouseVisitor visitor = new SpeakingHouseVisitor();
...
// Doing it your way
visitor.visit(acceptor);
// Output: Inside a HouseAcceptor
// Doing it the right way
acceptor.accept(visitor);
// Output:
// Inside a House
// Inside a Kitchen
// Inside a LivingRoom
Note that if you do it your way, the runtime type of your acceptor will not make a difference: the static type will be used. By doing double dispatch you ensure that both runtime types are used.
Using your version, the following will not compile:
List<BaseAcceptor> list = ...
for(BaseAcceptor ba: list)
vi.visit(ba)
The java compiler cannot determine (statically) what ba will be, so it cannot decide at compile time which visit method to call. You would need to write an additional method:
public void visit(BaseAcceptor ba){
if(ba instanceof AcceptorA)
visit((AcceptorA)ba);
else if(ba instanceof AcceptorB)
visit((AcceptorB)ba);
}
This is not necessary using the visitor pattern.
Because Visitors have no knowledge of how to navigate the private internal fields of a composed Object.
If you called Visitor.visit(something) then it would have to figure out if that something had private fields which needed transversal. To do that, you need that something to accept your Visitor. Once you decide that navigation must be in the visited objects (and not the Visitor), then you realize that you need a call back to the Visitor to tell it what the next element in the navigation path is. Typically that's the accept(...) method; however, if you attempted to make accept(...) just a wrapper to initiate navigation (by delegation to the parameter), then you need a second set of methods to tell the Visitor you're entering X now, your entering Y now.
By using the GOF approach, one can safely subclass an item being visited and modify the visiting path to include or skip additional fields. This would not impact the existing Visitors because their interface would not change. One wouldn't need to recompile subclasses of the Visitor either.
By using your suggested approach, when one added a new type into the hierarchy of to-be-visited items, one would then need to recompile all the visitors, even the visitors had no interest in the new type.
A good compromise would be:
public interface Visitable {
public void accept(Visitor v);
}
were all your "data hierarchy" implements Visitable, and your Visitor has a "convenience method" like so
public abstract class Visitor {
public void initiate(Visitable v) {
v.accept(this);
}
public abstract void accept(...);
public abstract void accept(...);
public abstract void accept(...);
}
But it's up to you if having an interface is preferable to such a base class. To me I'd favor the more loosely coupled interface, but opinions differ.
you have no double dispatch. accept usually takes an abstract visitor as an argument.

Categories