Using Generalization properly - java

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

Related

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.

Is it possible to make a reference to an abstract class method in a class method that doesn't extend it?

I'm taking a tutorial on building a simple behavior Ai. It's 'brain' class is abstract and contains states as in "running","success","failure". Now in the my ai unit - droid class i have a method to start the brain of the droid up.
public void update(){
if(Routine.getState()==null){
Routine.start();
}
Routine.act(this, board);
}
Now this isn't possible in java because it's a static reference to a non-static method.
The routine abstract class that i'm trying to reference to here goes like this :
public abstract class Routine {
public enum RoutineState{
Success,
Failure,
Running
}
protected RoutineState state;
protected Routine() { }
public void start(){
this.state = RoutineState.Running;
}
public abstract void reset();
public abstract void act(droid droid, board board);
public void succed(){
this.state = RoutineState.Success;
}
public void Fail(){
this.state = RoutineState.Failure;
}
public boolean isSuccess(){
return state.equals(RoutineState.Success);
}
public boolean isFailure(){
return state.equals(RoutineState.Failure);
}
public boolean isRunning(){
return state.equals(RoutineState.Running);
}
public RoutineState getState(){
return state;
}
}
I've tried copying the method to one of the classes that extends the Routine, but that doesn't work either the same problem comes up.
The static requirement is especially difficult on start() and act() that contain this. and are initializers.
I can only make the method update() like it is, in the routine where i initialize the droid and the board it will be acting on - but i don't see this quite like the solution i'd like to have.
For sure, you can reference an abstract class and call its abstract classes, but the object you exactly reference should be an extender of the abstract class.
For example, create a list of different objects, all extending one abstract class.
public abstract class ExAbstract { public abstract void abstractmethod() {...} }
public class ExampleA extends ExAbstract { #Override... }
public class ExampleB extends ExAbstract { #Override... }
...
List<ExAbstract> list = new ArrayList<>();
list.add(new ExampleA());
list.add(new ExampleB());
...
And then, you can call abstract method on it.
for (ExAbstract test : list){
test.abstractmethod();
}
(Or Java 8)
list.forEach(ExAbstract::abstractmethod);
But if object wasn't extending abstact, and it was abstract itself, it would give an error.
EDIT: In your case, with Routine class, you should make a constructor for it, and then make a new object. (I see you have a constructor already...) If you want to use a method without creating an object, use static
In Routine.java:
public Routine(ExampleArg a){
this.a = a;
}
In your Routine call:
Routine r = new Routine(a);
r.start();

Checking `instanceof` while iterating through a loop

I have class structure where
public abstract class AbstractBuilding implements some non-relevant
interfaces for this question.
public abstract class AbstractAnimalBuilding extends AbstractBuiling
And small number of classes following this structure:
public class AnimalBuildingA extends AbstractAnimalBuilding
public class AnimalBuildingB extends AbstractAnimalBuilding
public class AnimalBuildingC extends AbstractAnimalBuilding
public class AnimalBuildingD extends AbstractAnimalBuilding
In a totally separate class I have the following method:
#FXML
private Button btnAnimalBuildingA;
#FXML
private Button btnAnimalBuildingB;
#FXML
private Button btnAnimalBuildingC;
#FXML
private Button btnAnimalBuildingD;
for (AbstractAnimalBuilding animalBuilding: animalBuildings){
if (animalBuilding instanceof AnimalBuildingA) {
changeButtonDisplay(btnAnimalBuildingA)
} else if (animalBuilding instanceof AnimalBuildingB){
changeButtonDisplay(btnAnimalBuildingB)
} else if (animalBuilding instanceof AnimalBuildingC) {
changeButtonDisplay(btnAnimalBuildingC)
} else if (animalBuilding instanceof AnimalBuildingD){
changeButtonDisplay(btnAnimalBuildingD)
//Do something specific here
}
}
private void changeButtonDisplay(Button buttonToChange){
button.setVisible(true);
}
Where animalBuildings is a Set<AbstractAnimalBuilding> containing any combination of AnimalBuildingX's.
Assuming the structure at the top needs to be kept (eg, AnimalBuildingX HAS to extend AbstractAnimalBuilding), what would be a better approach than the multiple if-then-else statements in determining what kind of building animalBuilding is?
Would it feasible to simply create a new Interface as outlined in this question and have each AnimalBuildingX implement it while still extending AbstractAnimalBuilding or is there a way I can do it using the structure I currently have.
This is difficult to answer in general without more context.
One possibility is to create an abstract method in AbstractBuilding and implement it differently in the subclasses.
Another possibility is to use the visitor pattern.
It depends on the action you want to take on behalf of the derived class type. If an action has to be taken which can be perfomed without the need, that the calling class knows the concrete implementation of AnimalBuilding the interface method is appropriate. This usually is the case if you can find a common method description which is implemented differently for each concrete class (e.g. getName()).
If you need to do specific actions dependent on the concrete class (e.g. AnimalBuildingA differs from AnimalBuldingB), you can implement the visitor pattern:
public abstract class AbstractAnimalBuilding {
...
public abstract void accept(AnimalBuildingVisitor v);
}
public interface class AnimalBuildingVisitor<T> {
public T visit(AnimalBuildingA a);
public T visit(AnimalBuildingB b);
...
}
The implementation of the accept-method usually is the one liner
return v.visit(this);
Then you create an implementation of the Abstract visitor which does the work you want to perform in the loop. The loop then looks like this
ConcreteAnimalBuildingVisitor v;
for (AbstractAnimalBuilding animalBuilding: animalBuildings)
animalBuilding.accept(v);
This way, the concrete class "identifies" itself to the concrete visior which then can perform the appropriate action.
You can keep your current structure and achieve what you desire by using generics:
First we need to define a generic handler interface:
public interface AnimalBuildingHandler<T extends AbstractAnimalBuilding> {
void handle(T type);
}
And then, in your own custom class, we can implement specific function for each types:
/* Here you can define all */
public void handleAnimalBuildingA(AnimalBuildingA animalBuildingA) {
/**
* Implement your custom handling here
*/
System.out.println("Handling AnimalBuildingA" + animalBuildingA);
}
public void handleAnimalBuildingB(AnimalBuildingB animalBuildingB) {
/**
* Implement your custom handling here
*/
System.out.println("Handling AnimalBuildingA" + animalBuildingB);
}
And then, we can create a magic handler class that implements the above AnimalBuildingHandler interface by mapping handlers to types just like this:
private Map<Class<? extends AbstractAnimalBuilding>, AnimalBuildingHandler<? extends AbstractAnimalBuilding>> handlersMapping;
{ /* default instance initializer */
handlersMapping = new HashMap<>();
handlersMapping.put(AnimalBuildingA.class, new AnimalBuildingHandler<AnimalBuildingA>() {
#Override
public void handle(AnimalBuildingA type) {
handleAnimalBuildingA(type);
}
});
handlersMapping.put(AnimalBuildingB.class, new AnimalBuildingHandler<AnimalBuildingB>() {
#Override
public void handle(AnimalBuildingB type) {
handleAnimalBuildingB(type);
}
});
}
#Override
public void handle(AbstractAnimalBuilding type) {
AnimalBuildingHandler abh = handlersMapping.get(type.getClass());
abh.handle(type);
}
And finally, the test method:
public <T extends AbstractAnimalBuilding> void test() {
List<T> allAnimalBuildings = new ArrayList<>();
allAnimalBuildings.add((T) new AnimalBuildingA());
allAnimalBuildings.add((T) new AnimalBuildingB());
for (AbstractAnimalBuilding aab : allAnimalBuildings) {
handle(aab);
}
}

java mutant design pattern and compiler error 'Interface' cannot be inherited with different type arguments 'TypeA' and 'TypeB'

I am way over thinking this: What I am trying to do is [hopefully not reinvent the wheel and] come up w/ a [Android] Java eventing mechanism that allows subclasses to pre-define an arbitrary set of "features" with getters and setters that fire individual callbacks.
I think I am fusioning some combination of Command, Visitor, Decorator, Facade and Observer patterns here, and confusing myself along the way.
I have been programming for well over 20 years, but I feel like a n00b on this fairly simple problem! :(
I have searched SO for the compiler error and read many of the results, but I still haven't found a solution that works for me.
(How to make a Java class that implements one interface with two generic types? seems to be the most relevant one that I have found, but I also want to generically get the values and fire events to callbacks when they are set).
First, let the below mostly valid code speak for itself...
interface IFeature
{
}
interface IFeatureCallbacks<T extends IFeature>
{
boolean onChanged(Feature<T> c);
}
public static class Feature<T extends IFeature>
{
private Set<IFeatureCallbacks<T>> listeners = new LinkedHashSet<>();
public void addListener(IFeatureCallbacks<T> listener)
{
listeners.add(listener);
}
public void removeListener(IFeatureCallbacks<T> listener)
{
listeners.remove(listener);
}
protected void onChanged()
{
for (IFeatureCallbacks<T> listener : listeners)
{
listener.onChanged(this);
}
}
}
//
interface IFeatureA
extends IFeature
{
int getA();
}
interface IFeatureACallbacks
extends IFeatureCallbacks<IFeatureA>
{
}
public static class FeatureA
extends Feature<IFeatureA>
implements IFeatureA
{
private int a;
public void setA(int value)
{
a = value;
onChanged();
}
#Override
public int getA()
{
return a;
}
}
//
interface IFeatureB
extends IFeature
{
boolean getB();
}
interface IFeatureBCallbacks
extends IFeatureCallbacks<IFeatureB>
{
}
public static class FeatureB
extends Feature<IFeatureB>
implements IFeatureB
{
private boolean b;
public void setB(boolean value)
{
b = value;
onChanged();
}
#Override
public boolean getB()
{
return b;
}
}
//
interface IDeviceWithFeatureA
extends IFeatureA
{
}
interface IDeviceWithFeatureACallbacks
extends IFeatureACallbacks
{
}
public static class DeviceWithFeatureA
extends Feature<IDeviceWithFeatureA>
implements IDeviceWithFeatureA
{
FeatureA a = new FeatureA();
public void addListener(IDeviceWithFeatureACallbacks listener)
{
a.addListener(listener);
}
public void setA(int value)
{
a.setA(value);
}
#Override
public int getA()
{
return a.getA();
}
}
//
interface IDeviceWithFeatureB
extends IFeatureB
{
}
interface IDeviceWithFeatureBCallbacks
extends IFeatureBCallbacks
{
}
public static class DeviceWithFeatureAB
extends Feature<IDeviceWithFeatureB>
implements IDeviceWithFeatureB
{
FeatureB b = new FeatureB();
public void addListener(IDeviceWithFeatureBCallbacks listener)
{
b.addListener(listener);
}
public void setB(boolean value)
{
b.setB(value);
}
#Override
public boolean getB()
{
return b.getB();
}
}
The above code seems to work fine, albeit something about it smells a bit off.
The problem is when I try to do this:
interface IDeviceWithFeatureAAndFeatureB
extends IFeatureA, IFeatureB
{
}
/*
Compiler error:
'IFeatureCallbacks' cannot be inherited with different type arguments 'IFeatureA' and 'IFeatureB'
*/
interface IDeviceWithFeatureAAndFeatureBCallbacks
extends IFeatureACallbacks, IFeatureBCallbacks
{
}
public static class DeviceWithFeatureAB
extends Feature<IDeviceWithFeatureAAndFeatureB>
implements IDeviceWithFeatureAAndFeatureB
{
FeatureA a = new FeatureA();
FeatureB b = new FeatureB();
public void addListener(IDeviceWithFeatureAAndFeatureBCallbacks listener)
{
a.addListener(listener);
b.addListener(listener);
}
public void setA(int value)
{
a.setA(value);
}
#Override
public int getA()
{
return a.getA();
}
public void setB(boolean value)
{
b.setB(value);
}
#Override
public boolean getB()
{
return b.getB();
}
}
I am less interested in trying to figure out how to make what I am trying to do compilable, and I am more interested in what about my abuse of a pattern is way off base so that I can re-write it to be both simpler and compile.
You are abusing the basic "pattern" of OOP -- inheritance. The adage is that "favor composition over inheritance". Think in terms of "contains", instead of "is-a".
Take Zoo for example. A zoo is just a bunch of animals, right? So naturally, we may want to declare Zoo as subtype of Set<Animal>. Perhaps even have class Zoo extends HashSet<Animal>.
However, that is likely a wrong design. A zoo is actually a lot of things. It contains a set of animals, sure; but it also contains a set of people (as workers, not exhibits (although...) ). So it's better to
class Zoo
Set<Animal> animals(){ ... }
Set<Person> workers(){ ... }
Anywhere we need to treat a zoo as a set of animals, just use zoo.animals(); think of it as a type cast, or projection. We don't need inheritance here.
In your design, you have too many types; what's worse, too many type relationships. It seems that you simply need one generic class that reads/writes value of T, and contains listeners of T
class Feature<T>
T value;
// getter
// setter
Set<ChangeListener<T>> listeners;
interface ChangeListener<T>
void onChange(T oldValue, T newValue)
A device contains a bunch of features
class SomeDevice
Feature<Integer> featureA = new Feature<>();
Feature<Boolean> featureB = new Feature<>();
That's it. You can operate on feature A of the device by operating on itsfeatureA.

Decoupling States using the State Pattern

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.

Categories