Visitor pattern: overriding vs overloading - java

For implementing a Visitor Pattern in Java you can use Overriding or Overloading. Does the choice depends or is it always preferable to choose one of the two? Because I don't see no disadvantages. Because I think the first and third example will always do the job?
Visitor with overriding
public interface Visitor {
public void visitX(X x);
public void visitY(Y y);
}
public class ConcreteVisitor {
public void visitX(X x) { ... }
public void visitY(Y y) { ... }
}
public abstract class XY {
public abstract void accept(Visitor v);
}
public class X extends XY {
// alternative: one implementation with reflection possible in super class
public void accept(Visitor v) {
v.visitX(this);
}
}
public class Y extends XY {
// alternative: one implementation with reflection possible in super class
public void accept(Visitor v) {
v.visitY(this);
}
}
Visitor with overloading
public interface Visitor {
public void visit(XY xy); // dummy (couldn't otherwise been used in XY class)
public void visit(X x);
public void visit(Y y);
}
public class ConcreteVisitor {
public void visit(XY xy) { ... }
public void visit(X x) { ... }
public void visit(Y y) { ... }
}
public abstract class XY {
public void accept(Visitor v) {
v.visit(this); // Which is the compile-time/static type of this? XY?
}
}
public class X extends XY {
}
public class Y extends XY {
}
Better Visitor with overloading
public interface Visitor {
public void visit(X x);
public void visit(Y y);
}
public class ConcreteVisitor {
public void visit(X x) { ... }
public void visit(Y y) { ... }
}
public abstract class XY {
public abstract void accept(Visitor v);
}
public class X extends XY {
public void accept(Visitor v) {
v.visit(this);
}
}
public class Y extends XY {
public void accept(Visitor v) {
v.visit(this);
}
}

The Visitor pattern is in essence about covering an important use case of double dispatch in a single-dispatch language. It leverages the single-dispatch mechanism in a two-step idiom. Therefore if you use reflection for one of those two steps, you are no longer implementing Visitor.
The question of whether or not to use overloading is a minor point because it comes down to nothing more than the choice of name for all the visit methods. You can use either, but overloading makes more sense in professional code. While studying the pattern, separate names will make it easier to understand the Visitor pattern, which is a bit notorious for its convolutedness.

This is true of any behavior, not just Visitor. You can choose either one, of course. Both work.
Sounds like a rehash of the "interface or abstract class?" question. You prefer abstract when there can be meaningful, non-abstract default behavior. Interfaces have no default, so every user is forced to implement the method. No assumptions are possible.

Related

How can dynamic behaviors change state in Java?

I'm working with students in my Java class on a simple Zork-like environment in which the player goes from location to location encountering items. The items should have dynamic behaviors, so that a book is readable until you burn it, or a duck can fly until it flies too long and tires out. And so on.
The students and I have grokked the basic Strategy pattern (I'm adapting from Head First Design Patterns, and leaving out boilerplate):
public class Duck {
String name;
Int health;
FlyBehavior flyBehavior;
public void performFly() {
flyBehavior.fly();
}
public void setFlyBehavior(FlyBehavior f) {
flyBehavior = f;
}
}
public interface FlyBehavior {
public void fly();
}
public class FlyGracefully implements FlyBehavior {
public void fly() {
System.out.println("I fly so gracefully!");
}
}
public class TooTiredToFly implements FlyBehavior {
public void fly() {
System.out.println("I'm too tired to fly.");
}
}
Sparing the details of the main method, this lets us switch different flying behaviors into our Duck. This is easy because it returns a void and prints to sysout.
But what if we need the behavior to interact with the state of the Duck? Let's say that:
When the duck becomes too tired to fly, its name changes to "Exhausted Duck." Other behaviors can change its name, too.
When the duck is attacked (gonna happen), its health goes down. When its health is too low, its flyBehavior switches out to the TooTiredToFly behavior.
But I'm assuming that dynamic behaviors, at least in this pattern, have no access to the state of the object they're in.
Is there a general strategy for creating dynamic behaviors that interact with the state of the object they're in? I would like to teach something comprehensible, so put yourself in the mind of intermediate-level high school programmers.
Based on my comment above, something along these lines...
// Creating an interface for flyable things e.g. Duck, Airplane, etc.
// You don't have to do this. You could just pass your Duck
// object instead and call its methods directly.
public interface Flyable {
void performFly();
}
public class Duck implements Flyable {
// All your Duck stuff as above in here.
}
public abstract class FlyBehavior {
private Flyable parent;
public FlyBehavior(Flyable parent) {
this.parent = parent;
}
public abstract void fly();
protected Flyable getParent() {
return this.parent;
}
}
public class FlyGracefullyBehavior extends FlyBehavior {
public FlyGracefullyBehavior(Flyable parent) {
super(parent);
}
#Override
public void fly() {
// Now you can get access to the original parent here.
Flyable parent = this.getParent();
}
}
public class TooTiredToFlyBehavior extends FlyBehavior {
public TooTiredToFlyBehavior(Flyable parent) {
super(parent);
}
#Override
public void fly() {
// Now you can get access to the original parent here.
Flyable parent = this.getParent();
}
}
Or, you could simply pass parent state in the fly method of your FlyBehavior classes i.e. behavior.fly(state); It's up to you :)
Here's a basic example of using the Strategy pattern as you have described. I'm trying to keep it as simple as possible so some best practices were ignored (e.g. declaring constants) so you can focus on the Strategy design and not be overwhelmed with information.
public interface Animal
{
public String getName();
public void attacked(int health);
}
public interface Bird extends Animal
{
public void fly();
}
public class Duck implements Bird
{
private Int health = 100;
private DuckBehavior state = new HealthyDuck();
public getName()
{
return state.getName();
}
public void fly()
{
state.fly();
}
public void attacked(int hitpoints)
{
health = health - hitpoints;
if (health < 50) {
state = new HurtDuck();
} else if (health < 0) {
state = new DeadDuck();
}
}
}
interface DuckBehavior
{
public getName();
public void fly();
}
public class HealthyDuck implements DuckBehavior
{
public getName()
{
return "Healthy Duck";
}
public void fly()
{
System.out.println("I fly so gracefully!");
}
}
public class HurtDuck implements DuckBehavior
{
public getName()
{
return "Hurt Duck";
}
public void fly()
{
System.out.println("I'm too tired to fly.");
}
}
public class DeadDuck implements DuckBehavior
{
public getName()
{
return "Dead Duck";
}
public void fly()
{
System.out.println("I'm too dead to fly.");
}
}
Lets add a new interface in the design as below
Flyable.java
public interface Flyable{
public void modifyTargetName(String newName);
}
Lets Modify the FlyBehavior.java and its implementation classes. Lets define a method public void setFlyableTarget( Flyable target ) in it.
FlyBehavior.java
public interface FlyBehavior {
public void fly();
public void setFlyableTarget( Flyable target );
}
FlyGracefully.java
public class FlyGracefully implements FlyBehavior {
public void fly() {
System.out.println("I fly so gracefully!");
}
public void setFlyableTarget( Flyable target ){
target.modifyTargetName("GraceFul Flyer");
}
}
TooTiredToFly.java
public class TooTiredToFly implements FlyBehavior {
public void fly() {
System.out.println("I'm too tired to fly.");
}
public void setFlyableTarget( Flyable target ){
target.modifyTargetName("TiredFlyer");
}
}
Duck.java let it implement Flyable.java
public class Duck implements Flyable{
String name;
Int health;
FlyBehavior flyBehavior;
public void modifyTargetName(String newName){
this.name = newName;
}
public void performFly() {
flyBehavior.fly();
}
public void setFlyBehavior(FlyBehavior f) {
flyBehavior = f;
f.setFlyableTarget(this);
}
}
The good thing here is we do not expose concrete implementation and hence code remains unit testable and good for adaptation to changes. It adheres to the DIP : Dependency Inversion Principle as well.
One general point I'd like to make: Don't modify internal behavior of an object, it's rude. I mean, there should not be a setFlyBehavior() method, that is an internal attribute of the Duck.
Also, think about who is responsible for what. Once a Duck is constructed, you can ask a Duck to fly, and you can make the Duck take Damage. How those things change the Duck is none of our business at that point.
On a more practical note, this is how that might look:
public interface Being {
boolean isDamaged();
}
public interface FlyingBehavior {
void fly();
}
public class GracefulFlyingBehavior implements FlyingBehavior {
...
}
public class TiredFlyingBehavior implements FlyingBehavior {
...
}
public class BirdFlyingBehavior implements FlyingBehavior {
private int tiredness;
...
public BirdFlyingBehavior(Being bird) {
...
}
#Override
public void fly() {
if (bird.isDamaged() || isTired()) {
tiredFlying.fly();
} else {
gracefulFlying.fly();
tiredness++; // Or whatever...
}
}
}
The point is, that the behavior itself should be responsible for deciding whether the flying can take place. It is after all the "strategy" for flying, so this logic needs to be there.
Then you can construct a duck something like this:
public Duck(String name, ... ) {
...
this.flyBehavior = new BirdFlyingBehavior(this);
}
or something similar. The point here is that once that strategy is set, it should stay internal to the Duck, there should be no way to modify that directly anymore.
Of course there might be additional features (you might want to move "tiredness" to the general "health" of a being), but the concepts should not change. Objects should hide their internal state, this requires "responsibilities" to be at the right place.

Choose implementation based on the type of the Object in Java

I have one parent type
public class IObject{}
and can have a lot of sub-classes (even new ones in the future)
public class Object1 extends IObject{}
public class Object2 extends IObject{}
public class Object3 extends IObject{}
...
public class ObjectN extends IObject{}
Then based on the type of these objects I have to do different operations.
public class StrategyForObject1(){void do{}}
public class StrategyForObject2(){void do{}}
public class StrategyForObject3(){void do{}}
...
public class StrategyForObjectN(){void do{}}
So I want from my Context class:
public Conext {
IObject o;
public void setObject(IObject o) {
this.o = o;
}
void logic() {
if (o instanceOf Object1) {
new StrategyForObject1().do();
}
if (o instanceOf Object2) {
new StrategyForObject2().do();
}
if (o instanceOf Object3) {
new StrategyForObject3().do();
}
...
if (o instanceOf ObjectN) {
new StrategyForObjectN().do();
}
}
}
So based on the type to execute different algorithms, but I want to be extensible like in Strategy pattern if I need to add new sub-class of IObject just to add new StrategyForObject**N** class, but not to change the Conext class.
In Strategy pattern we have to specify the Strategy but here we have to do the opposite: to choose the strategy based on the type of the object. How to do that in Java in the best way?
Edit:
The IObject can not be changed in order to add additional methods.
I must separate logic from data,so it is not desirable to add implementation of the logic in Object1 class for example.
I think you need to implement the visitor pattern. Basically for what you have it would look something like this:
interface IObjectVisitor {
void visit(IObject1 obj1);
void visit(IObject2 obj2);
...
void visit(IObjectN objN);
}
interface IObjectVisitable {
void accept(IObjectVisitor visitor);
}
public abstract class IObject implements IObjectVisitable {
...
}
public class IObject1 extends IObject {
public void accept(IObjectVisitor visitor) {
visitor.visit(this);
}
}
public class IObject2 extends IObject {
public void accept(IObjectVisitor visitor) {
visitor.visit(this);
}
}
...
public class IObjectN extends IObject {
public void accept(IObjectVisitor visitor) {
visitor.visit(this);
}
}
public class SomeLogicIObjectVisitor implements IObjectVisitor {
void visit(IObject1 obj1) {
//something with obj1
}
void visit(IObject2 obj2) {
//something with obj2
}
...
void visit(IObjectN objN) {
//something with objN
}
}
Then you haven some logic to apply to some IObject like this:
public void someLogic(IObject obj) {
SomeLogicIObjectVisitor visitor = new SomeLogicIObjectVisitor():
visitor.visit(obj);
}
Object-Oriented wise, this is the best pattern you can implement. The reason is because it allows you for a modular and extensible approach, applying the right separation of concerns. Look at the answer provided by #nhouser9 for instance. While defining abstract void do(); in IObject seems to work at first glance, you would be embedding business logic inside your domain object, which most likely doesn't belong there. Also, if now you consider some other logic, lets call it, "logic2" now you have no option but to create abstract void do2(); on every IObject implementation, and continue to embed business logic there. With the visitor pattern, IObject implementations don't change, and you don't embed any logic inside the IObjects, simply just create a new visitor, Logic2IObjectVisitor and implement the logic of each IObject implementation there. And you'd call it like this:
public void someLogic2(IObject obj) {
Logic2IObjectVisitor visitor = new Logic2IObjectVisitor():
visitor.visit(obj);
}
First, your IObject class should be abstract, as it is only intended to be extended by other classes. Then you can declare a method inside it that must be overridden by classes which inherit from it, like this:
public abstract class IObject {
abstract void do();
}
Then all of the classes that implement it must override that method with your custom logic:
public class Object1 extends IObject {
#Override
void do() {
//custom logic
}
}
In other words, you should be putting do() inside Object1 instead of StrategyForObject1.
This structure will allow you to call do() on a generic object of type IObject, as all children of IObject will implement the do() method. So in your logic method, you can just do this:
void logic(){
o.do();
}
Have a look at the Visitor Pattern. I think its exactly what you are looking for.
Edit: To clarify:
import java.util.Arrays;
import java.util.List;
public class Test {
public static abstract class IObject {
public abstract void doSomeWork(StrategyVisitor strat);
}
public static class Object1 extends IObject {
#Override
public void doSomeWork(StrategyVisitor strat) {
strat.doWork(this);
}
}
public static class Object2 extends IObject {
#Override
public void doSomeWork(StrategyVisitor strat) {
strat.doWork(this);
}
}
public static class Object3 extends IObject {
#Override
public void doSomeWork(StrategyVisitor strat) {
strat.doWork(this);
}
}
public static interface StrategyVisitor {
void doWork(Object1 o);
void doWork(Object2 o);
void doWork(Object3 o);
}
public static void main(String[] args) {
List<IObject> objs = Arrays.asList(new Object1(), new Object2(), new Object3());
StrategyVisitor visitor = new StrategyVisitor() {
#Override
public void doWork(Object1 o) {
System.out.println("Object1");
}
#Override
public void doWork(Object2 o) {
System.out.println("Object2");
}
#Override
public void doWork(Object3 o) {
System.out.println("Object3");
}
};
objs.stream().forEach(o -> o.doSomeWork(visitor));
}
}
(See https://en.wikipedia.org/wiki/Visitor_pattern)
IObject could have an abstract method, do().
Then Context's logic() method just calls o.do().
This is a classic example of polymorphism.

Avoid instanceof in Java interface implementation

Assuming the following situation:
public interface A {
void a1();
void a2();
}
public interface B {
void b1(A a);
}
public class ImplA implements A {
// interface methods
void a1() {};
void a2() {};
// ImplA specific methods
void a3() {};
}
public class ImplB implements B {
void b1(A a) {
if(a instaceof ImplA) { // avoid instanceof test and cast
((ImplA)a).a3();
}
}
}
Would it be possible by some architectural voodoo to avoid an instanceof check in ImplB.b1()? ImplA and ImplB are in the same package and closely related to each other. I read somewhere, that the use of instanceof is a hint for a "no-so-good" interface design. Any recommendations? Thanks alot!
You could use a Visitor pattern to avoid the instanceof cast
public interface Visitor {
void visitImplA(ImplA toVisit);
}
public class VisitorImpl implements Visitor {
#Override
public void visitImplA(ImplA toVisit) {
toVisit.a3();
}
}
public interface A {
void a1();
void a2();
void accept(Visitor visitor);
}
public interface B {
void b1(A a);
}
public class ImplA implements A {
// interface methods
void a1() {};
void a2() {};
// ImplA specific methods
void a3() {};
void accept(Visitor visitor) {
visitor.visitImplA(this);
}
}
public class ImplB implements B {
void b1(A a) {
a.accept(new VisitorImpl());
}
}
This would eliminate all you instanceof checks and divide them into the visitor and the implementing classes, this pattern would suffice in the case where you'd be doing the same stuff after most of the instanceof checks, otherwise you'd need a lot of implementations of the Visitor interface
The VooDoo you want is composition. You can solve that using Visitor dessign pattern. But ther is some penalty when you are using it. Or you can create onther interface that will be used to invoke that a3 method.
The case varry. The reason of question might be that your architecture is not consist and you trying to do something strange or your class perform to many things.

Interfaces - solving ambiguous error

Lets look at the following example:
public class BothPaintAndPrintable implements Paintable,Printable{
public void print() {}
public void paint() {}
}
public interface Paintable {
public void paint();
}
public interface Printable {
public void print();
}
public class ITest {
ArrayList<Printable> printables = new ArrayList<Printable>();
ArrayList<Paintable> paintables = new ArrayList<Paintable>();
public void add(Paintable p) {
paintables.add(p);
}
public void add(Printable p) {
printables.add(p);
}
public static void main(String[] args) {
BothPaintAndPrintable a= new BothPaintAndPrintable();
ITest t=new ITest();
t.add(a);//compiliation error here
}
}
What if I want BothPaintAndPrintable instances to be added to each of the ArrayLists?
One way would be overloading the method with a BothPaintAndPrintable parameter, but I'm trying to see alternatives since doing that might reduce code reuseability. Does anyone have another idea?
You need a third overload:
public <T extends Object&Paintable&Printable> void add(T t) {
paintables.add(t);
printables.add(t);
}
This makes the erasure add(Object), so it doesn't conflict with the other methods, but it does restrict the input to implementors of both Paintable and Printable.
(Guava had to use this trick for Joiner with Iterator and Iterable, because some evil classes out there implemented both, even though it's a terrible idea.)
I would go with a general add(Object o) method, then checking for instanceof, and putting the Object into the according lists.
If the passed Object implements neither interface, throwing an InvalidArgumentException might be a good idea.
Not sure about the best answer as I can't find a way I actually like!
You could use generics, but I don't like either the "instanceof" tests, nor the casts required:
import java.util.ArrayList;
class BothPaintAndPrintable implements Paintable, Printable {
public void print() {
}
public void paint() {
}
}
interface Paintable {
public void paint();
}
interface Printable {
public void print();
}
public class ITest<T> {
ArrayList<Printable> printables = new ArrayList<Printable>();
ArrayList<Paintable> paintables = new ArrayList<Paintable>();
public void add(T p) {
if (p instanceof Paintable) {
paintables.add((Paintable) p);
}
if (p instanceof Printable) {
printables.add((Printable) p);
}
}
public static void main(String[] args) {
BothPaintAndPrintable a = new BothPaintAndPrintable();
ITest<BothPaintAndPrintable> t = new ITest<BothPaintAndPrintable>();
t.add(a);
}
}
Okay I do like the correct answer; however, there is another solution I should point out to the OP.
public static void main(String[] args) {
BothPaintAndPrintable a= new BothPaintAndPrintable();
ITest t=new ITest();
t.add((Paintable)a);
t.add((Printable)a);
}
This works without adding the third member, and even works if you decide to add more interfaces down the road.

Java Enums: Implementing methods After Declaration?

Consider the simple example below of implementing a method in an Enum. One problem with this method is that, when you have a lot of enum instances, you visually can no longer see them all at once, as a list. That is, if we had many toys, I would like to see "DOLL, SOLDIER, TEDDYBEAR, TRAIN, ETC", together, in one long list, and then after that list I could implement any needed methods, e.g. methods that are abstract in the enum itself.
Is there any way to do this? Or do you have to implement the methods when you declare the individual enum instances, as in the example below?
public enum Toy {
DOLL() {
#Override public void execute() {
System.out.println("I'm a doll.");
}
},
SOLDIER() {
#Override public void execute() {
System.out.println("I'm a soldier.");
}
};
//abstract method
public abstract void execute();
}
One way that comes to mind is to leave the implementation of the abstract methods to separate implementation classes, something like:
interface ToyBehaviour {
void execute();
}
public enum Toy {
DOLL(new DollBehaviour()),
SOLDIER(new SoldierBehaviour());
private final ToyBehaviour behaviour;
Toy(ToyBehaviour impl) {
behaviour = impl;
}
public void execute() {
behaviour.execute();
}
}
class DollBehaviour implements ToyBehaviour {
public void execute() {
System.out.println("I'm a doll.");
}
}
This setup would allow you to create behaviour classes in separate files in the case that your implementation has enough complexity to warrant separation.
In the case that the implementation is simple enough to include it into the one enum class, you can put the interface and behaviour classes as children of the enum class:
public enum Toy {
// enum values
DOLL(new DollBehaviour()),
SOLDIER(new SoldierBehaviour());
private final ToyBehaviour behaviour;
Toy(ToyBehaviour impl) {
behaviour = impl;
}
public void execute() {
behaviour.execute();
}
// behaviour interface
interface ToyBehaviour {
void execute();
}
// behaviour implementation (sub)classes
static class DollBehaviour implements ToyBehaviour {
public void execute() {
System.out.println("I'm a doll.");
}
}
// etc ...
}
I would probably opt for the first implementation myself, unless the hierarchy of implementation classes is very trivial.
If you want more compact enum declarations, the only ways I can think of to do it are :
if you can construct your methods out of initializer variables:
public enum Toy {
DOLL("doll"),SOLDIER("soldier");
private Toy(String name){ this.name=name;}
public void execute(){ System.out.println("I'm a "+name );}
}
or, slightly more complicated, kind of the same with functions, if the behavior is more complex -
abstract class SomeToyMethod {
abstract void execute();
public SomeToyMethod DOLL_METHOD = new SomeToyMethod(){
public void execute(){ System.out.println("I'm a doll");})
public SomeToyMethod SOLDIER_METHOD = new SomeToyMethod(){
public void execute(){ System.out.println("I'm a soldier");})
public enum Toy {
DOLL(SomeToyMethod,DOLL_METHOD),SOLDIER(SomeToyMethod.SOLDIER_METHOD);
private Toy(SomeToyMethod method){ this.method=method;}
public void execute(){ method.execute();}
}
You could try something like:
public enum Toy {
DOLL,
SOLDIER,
ANOTHER_TOY;
public static void execute(Toy toy) {
switch(toy) {
case DOLL:
System.out.println("I'm a doll.");
break;
case SOLDIER:
System.out.println("I'm a soldier.");
break;
case ANOTHER_TOY:
System.out.println("I'm another toy.");
break;
}
}
}
Not very pretty but it keeps your enum declarations together.

Categories