My company's legacy code is suffering from prevalent usage of instanceof switch-casing, in the form of:
if(object instanceof TypeA) {
TypeA typeA = (TypeA) object;
...
...
}
else if(object instanceof TypeB) {
TypeB typeB = (TypeB) object;
...
...
}
...
...
To make things worse, several of the TypeX classes in questions are actually wrappers of classes found in 3rd party libraries.
The suggested approach of using the visitor design pattern and dedicated visitor design pattern wrappers on 3rd party classes as seen here (instanceof -> Visitor DP) and here (Visitor DP with 3rd party classes) seems like a good approach.
However, during a code review session where this approach was suggested, the question of the additonal overhead of boilerplate code required by each refactoring of the instaceof switch-casing has lead to this mechanism being declined.
I would like to fix this ongoing issue and I am considering a generic approach to the problem:
A utility class which will wrap the visitor design pattern with generic referencing to the visited objects. The idea is to implement the generic core of the visitor utility class once and only once, and provide specific implementations to the TypeX object behaviour where needed - hopefully even reusing some implementations via OO extention of the functionality implementing classes.
My question is - has anyone here done something similiar? If not - can you point out any pros/cons that might be relevant?
EDIT :
Too much boilerplate code = implementing the visitor design pattern specifically for each instance of an instanceof switch-case. This is obviously redundent and will cause a lot of code duplication, if the visitor DP is not implemented using generics.
As for the generic visitor DP utility I had in mind :
First of all, usage of reflection with the visitor DP as seen here.
Second, the following usage of generics (based on the reflective visitor):
public interface ReflectiveVisitor<GenericReturn,GenericMetaData>
{
public GenericReturn visit(Object o, GenericMetaData meta);
}
public interface ReflectiveVisitable<A,B>
{
public GenericReturn accept(Visitor visitor, GenericMetaData meta);
}
GenericReturn and GenericMetaData are interfaces aimed at providing any additionally required meta data for specific logics to be implemented, and to provide versatility for return types returned by the visitor DP.
Thanks in advance!
EDIT : Boiler plate coding when refactoring from instanceof to the visitor :
A common use case I'd have to handle is instanceof switchcasing in order to perform single API calls of concrete implementations :
public class BoilerPlateExample
...
if(object instanceof TypeA) {
((TypeA) object).specificMethodTypeA(...)......;
}
else if(object instanceof TypeB) {
((TypeB) object).completeyDifferentTypeBMethod(...)......;
}
...
...
As for the visitor design handling this?
public interface Visitor
{
// notice how I just binded my interface to a specific set of methods?
// this interface will have to be generic in order to avoid an influx of
// of dedicated interfaces
public void visit(TypeA typeA);
public void visit(TypeB typeB);
}
public interface Visitable
{
public void accept(Visitor visitor);
}
public class BoilerPlateExampleVisitable<T> implements Visitable
{
// This is basically a wrapper on the Types
private T typeX;
public BoilerPlateExampleVisitable (T typeX) {
this.typeX = typeX;
}
public void accept(Visitor visitor) {
visitor.visit(typeX);
}
}
public class BoilerPlateExampleVisitor implements Visitor
{
public void visit(TypeA typeA) {
typeA.specificMethodTypeA(...)......;
}
public void visit(TypeB typeB) {
typeB.completeyDifferentTypeBMethod(...)......;
}
}
public static final BoilerPlateExampleVisitor BOILER_PLATE_EXAMPLE_VISITOR = new BoilerPlateExampleVisitor();
public static void main(....) {
TypeA object = .....; // created by factory
BoilerPlateExampleVisitable boilerPlateVisitable = VisitableFactory.create(object); // created by dedicated factory, warning due to implicit generics
boilerPlateVisitable.accept(BOILER_PLATE_EXAMPLE_VISITOR);
}
TL;DR: Let's say that you have N classes with M operations each. You need the visitor pattern only if M may grow and N is already big. Else use polymorphism.
Maybe I will push an open door, because you already thought of this, but here are a few thoughts.
Visitor pattern
In the generic case, you will use the visitor pattern only if you want to add new operations without refactoring all classes. That is when M may grow and N is already big.
For every new operation, you create a new visitor. This visitor accepts the N classes and handles the operation for each of them:
public class NewOperationVisitor implements Visitor
{
public void visit(TypeA typeA) {
// apply my new operation to typeA
}
public void visit(TypeB typeB) {
// apply my new operation to typeB
}
...
}
Thus, you don't have to add the new operation to all the N classes, but you have to refactor every visitor if you add a class.
Polymorphism
Now, if M is stable, please avoid the visitor pattern: use polymorphism. Every class has a well defined set of methods (roughly one per operation). If you add a class, just define the known operations for that class:
public class TypeX implements Operator
{
public void operation1() {
// pretty simple
}
public void operation2() {
// pretty simple
}
}
Now, you have to refactor every class if you add an operation, but adding a class is very easy.
This tradeoff is explained in Clean Code by R. C. Martin (6. Objects and Data Structures, Data/Object Anti-Symmetry):
Procedural code [here: the visitor] makes it hard to add new data structures because all the functions must change. OO code makes it hard to add new functions because all the classes must change.
What you should do
As stated in a #radiodef comment, avoid reflection and other tricks. This will be worse than the issue.
Clearly separate where you really need the visitor pattern, and where you don't. Count classes and operations. I bet that, in most of the cases, you don't need the visitor pattern. (Your managers are probably right!). If you need the visitor pattern in 10 % of the cases, maybe the "additonal overhead of boilerplate code" will be acceptable.
Since several of your TypeX classes are already wrappers, you maybe need to wrap better. Sometimes, one wraps from bottom to top: "My 3rd party class has those methods: I will wrap the methods I need and forget the others. And I will keep the same names to keep it simple." Instead, you have to carefully define the service a TypeX class should provide. (A hint: look in your if ... instanceof ... bodies). A then wrap again the 3rd party libs to provide thoses services.
Really: avoid avoid reflection and other tricks.
What would I do?
You asked in a comment for a pseudo-code, but I can't give it to you since I have a method in mind, not a procedure or an algorithm.
Here's a minimal step by of step of what I would do in such a situation.
Isolate every "big instanceof switch" in a method
That's almost a medical advice! Before:
public void someMethod() {
...
...
if(object instanceof TypeA) {
TypeA typeA = (TypeA) object;
...
...
}
else if(object instanceof TypeB) {
TypeB typeB = (TypeB) object;
...
...
}
...
...
}
After:
public void someMethod() {
...
...
this.whatYouDoInTheSwitch(object, some args);
...
...
}
And:
private void whatYouDoInTheSwitch(Object object, some args) {
if(object instanceof TypeA) {
TypeA typeA = (TypeA) object;
...
...
}
else if(object instanceof TypeB) {
TypeB typeB = (TypeB) object;
...
...
}
}
Any decent IDE will do it for free.
If you are in a case that would need the Visitor pattern
Leave the code as this, but document it:
/** Needs fix: use Visitor Pattern, because... (growing set of operations, ...) */
private void whatYouDoInTheSwitch(Object object, some args) {
...
}
If you want to use polymorphism
The goal is to switch from:
this.whatYouDoInTheSwitch(object, other args);
To:
object.whatYouDoInTheSwitch(this, other args);
You have a little refactoring to do:
A. Create a method for every case in the big switch. All those methods should have the same signature, except for the type of the object:
private void whatYouDoInTheSwitch(Object object, some args) {
if(object instanceof TypeA) {
this.doIt((TypeA) object, some args);
}
else if(object instanceof TypeB) {
this.doIt((TypeB) object, some args);
}
}
Again, any IDE will do it for free.
B. Create an interface with the following method:
doIt(Caller caller, args);
Where Caller is the type of the class you are refactoring (the one that contains the big switch).
C. Make every TypeX implement this interface by converting every doIt(TypeX objX, some args) into a doIt(Caller, some args) method from TypeX. Basically, that is a simple find-replace: replace this by caller and objX by this. But this may be a little more time consuming than the rest.
D. Now, you have:
private void whatYouDoInTheSwitch(Object object, some args) {
if(object instanceof TypeA) {
((TypeA) object).doIt(this, some args);
}
else if(object instanceof TypeB) {
((TypeB) object).doIt(this, some args);
}
}
This is strictly equivalent to:
private void whatYouDoInTheSwitch(Object object, some args) {
if(object instanceof TypeA) {
object.doIt(this, some args);
}
else if(object instanceof TypeB) {
object.doIt(this, some args);
}
}
Because at runtime, the JVM will find the right method for the right class (that's polymorphism!). Thus, this is also equivalent to (if object has one of the enumerated types):
private void whatYouDoInTheSwitch(Object object, some args) {
object.doIt(this, some args);
}
E. Inline the method and you have in your Caller class:
public void someMethod() {
...
...
object.doIt(this, some args);
...
...
}
Actually, this is only a sketch, and many special cases could occur. But it is guaranteed to be relatively fast and clean. It may be done for a selected method only of for all methods.
Be sure to test, if possible, the code after every step. And be sure to choose the right names for the methods.
Seems like polymorphism. Such code could stem from a heterogene set of business object classes, like Excel ReportX, Zip, TableY, and actions like Open, Close, Save and such.
As it is, this kind of programming causes a huge coupling between classes, and has issues with completeness of all cases, extendibility.
In the case of polymorphism the actual wrapper for some bussiness object should provide Actions (Open, Save, Close).
This mechanism is similar to java swing, where an edit field has its list of actions (Cut, Copy, Paste and such), and a tree view an overlapping set of actions. Depending on the focus the actual actions will be installed in the menu actions.
A declarative specification might be in order: say an XML that "holds" beans and their actions.
Should you have some MVC paradigm on the radar, consider the following:
every action could have parameters. Use PMVC (my idea), a Parameters class apart from the Model class, as those infos have a different life cycle, and are constant.
The road hereto could be:
a prototype with two business objects and two actions.
refactoring with one polymorph business object containing all (old code).
slowly moving one class after another to their own business object.
the first removal from the polymorph business object being used to clean up the new architecture.
I would refrain from using inheritance (a BaseDocument with open/save) as this probably does not fit a more heterogeneous reality, and could cause parallel class hierarchies (XDoc with XContainer and XObject).
How it is actually done is still your work. I also would be eager to learn whether there exists an established paradigm.
Asked pseudo-code
One would need a bit of analysis with some prototype made - a proof of concept. However there is a discovery of (dynamic) capabilities/features.
public interface Capabilities {
<T> Optional<T> as(Class<T> type);
}
Add this interface to every case class, and you can do:
void f(Capabilities animal) {
int distance = 45;
animal.as(Flying.class).ifPresent(bird -> bird.fly(distance));
}
The infrastructure would be: first the registration of capabilities and discovery can be placed in a separate class.
/**
* Capabilities registration & discovery map, one can delegate to.
*/
public class CapabilityLookup implements Capabilities {
private final Map<Class<?>, Object> capabilitiesMap = new HashMap<>();
public final <T> void register(Class<T> type, T instance) {
capabilitiesMap.put(type, instance);
}
#Override
public <T> Optional<T> as(Class<T> type) {
Object instance = capabilitiesMap.get(type);
return instance == null ? Optional.empty()
: Optional.of(type.cast(instance));
}
}
Then the legacy classes can be augmented:
/** Extended legacy class. */
public class Ape implements Capabilities {
private final CapabilityLookup lookup = new CapabilityLookup();
public Ape() {
lookup.register(String.class, "oook");
}
#Override
public <T> Optional<T> as(Class<T> type) {
return lookup.as(type); // Delegate to the lookup map.
}
}
/** Extended legacy class. */
public class Bird implements Capabilities {
private final CapabilityLookup lookup = new CapabilityLookup();
public Bird() {
lookup.register(Flying.class, new Flying() {
...
});
lookup.register(Singing.class, new Singing() {
...
});
}
#Override
public <T> Optional<T> as(Class<T> type) {
return lookup.as(type); // Delegate to the lookup map.
}
}
As you can see with Bird the original code would move into the actual class of the interface, here into Bird, as the instance was created in the constructor. But instead of an anonymous class one could make a BirdAsFlying class, a kind of action class in java swing parlance.
An inner class has the advantage to access Bird.this.
The refactoring can be done incrementally. Add Capabilities to all "instanceof" legacy classes. An if-sequence would normally be one interface, but could also be two, or one interface with two methods.
Related
I design my game application and face some troubles in OOP design.
I want to know some patterns which can help me, because java have not any multiple extends option. I will describe my problem below, and also explain why multiple interface doesn't help me at all. Lets go.
What we want is "class is set of features". By feature I mean construction like:
field a;
field b;
field c;
method m1(){
// use, and change fields a,b,c;
}
method m2(){
// use, and change fields a,b,c;
}
//etc
So, basically the feature is a set of methods and corresponding fields. So, it's very close to the java interface.
When I talk that class implemets "feature1" I mean that this class contains ALL "feature needed" fields, and have realisation of all feature related methods.
When class implements two features the tricky part begins. There is a change, that two different features contains similar fields (names of this fields are equal). Let the case of different types for such fields will be out of scope. What I want - is "feature naming tolerance" - so that if methodA() from feature A change the field "common_field", the methodB from feature B, that also use "common_field" as field will see this changes.
So, I want to create a set of features (basically interfaces) and their implementations. After this I want to create classes which will extends multiple features, without any copy-paste and other crap.
But I can't write this code in Java:
public static interface Feature1 {
public void method1();
}
public static interface Feature2 {
public void method2();
}
public static class Feature1Impl implements Feature1 {
int feature1Field;
int commonField;
#Override
public void method1() {
feature1Field += commonField;
commonField++;
}
}
public static class Feature2Impl implements Feature2 {
int feature2Field;
int commonField;
#Override
public void method2() {
commonField++;
}
}
public static class MyFeaturedClass extends Feature1Impl, Feature2Impl implements Feature1, Features2 {
}
So, as you can see the problem are really complex.
Below I'll describe why some standart approaches doesn't work here.
1) Use something like this:
public static class MyFeaturesClass implements Feature1,Feature2{
Feature1 feature1;
Feature2 feature2;
#Override
public void method2() {
feature2.method2();
}
#Override
public void method1() {
feature1.method1();
}
}
Ok, this is really nice approach - but it does not provide "feature field name tolerance" - so the call of method2 will not change the field "commonField" in object corresponding the feature1.
2) Use another design. For what sake you need such approach?
Ok. In my game there is a "unit" concept. A unit is MOVABLE and ALIVE object.
Movable objects has position, and move() method. Alive objects has hp and takeDamage() and die() methods.
There is only MOVABLE objects in my game, but this objects isn't alive.
Also, there is ALIVE objects in my game, but this objects isn't movable (buildings for example).
And when I realize the movable and alive as classes, that implements interfaces, I really don't know from what I should extends my Unit class. In both cases I will use copy-paste for this.
The example above is really simple, actually I need a lot of different features for different game mechanics. And I will have a lot of different objects with different properties.
What I actually tried is:
Map<Field,Object> fields;
So any object in my game has such Map, and to any object can be applied any method. The realization of method is just take needed fields from this map, do its job and change some of them. The problem of this approach is performance. First of all - I don't want to use Double and Interger classes for double and int fields, and second - I want to have a direct accsess to the fields of my objects (not through the map object).
Any suggestions?
PS. What I want as a result:
class A implements Feature1, Feature2, Feature3, Feature4, Feature5 {
// all features has corresponding FeatureNImpl implementations;
// features 1-2-3 has "shared" fields, feature 3-4 has, features 5-1 has.
// really fast implementation with "shared field tolerance" needed.
}
One possibility is to add another layer of interfaces. XXXProviderInterface could be defined for all possible common fields, that define a getter and setter for them.
A feature implementation class would require the needed providers in the constructor. All access to common fields are done through these references.
A concrete game object class implementation would implement the needed provider interfaces and feature interfaces. Through aggregation, it would add the feature implementations (with passing this as provider), and delegate the feature calls to them.
E.g.
public interface Feature1 {
void methodF1();
}
public interface Feature2 {
void methodF2();
}
public interface FieldAProvider {
int getA();
void setA(int a);
}
public class Feature1Impl implements Feature1 {
private FieldAProvider _a;
Feature1Impl(FieldAProvider a) {
_a = a;
}
void methodF1() {
_a.setA(_a.getA() * 2);
}
}
// Similar for Feature2Impl
public class GameObject implements Feature1, Feature2, FieldAProvider
{
int _fieldA;
Feature1 _f1;
Feature2 _f2;
GameObject() {
_f1 = new Feature1Impl(this);
_f2 = new Feature2Impl(this);
}
int getA() {
return _fieldA;
}
void setA(int a) {
_fieldA = a;
}
void methodF1() {
_f1.methodF1();
}
void methodF2() {
_f2.methodF2();
}
}
However, I don't think this is an optimal solution
In short, I'd like to be able to group class instances by a superclass which does not implement a certain interface. But from the set of instances I'd like to call methods from the interface on those instances that implement that interface.
Some example code which might explain it.
class Building{
String c = "white";
Building(){
}
void printColor(){
println("The building is " + c);
}
void paint( String c ){
this.c = c;
}
void printBuildQuality(){
println("The build quality is average");
}
}
class SturdyFactoryBuilding extends Building implements Factory{
SturdyFactoryBuilding(){
super();
}
void printBuildQuality(){
println("The build quality is sturdy");
}
void printFactoryOutput(){
println("This factory makes stuff");
}
}
class ShakyFactoryBuilding extends Building implements Factory{
ShakyFactoryBuilding(){
super();
}
void printBuildQuality(){
println("The build quality is shaky");
}
void printFactoryOutput(){
println("This factory makes slightly different stuff");
}
}
public interface Factory{
public void printFactoryOutput();
}
Building building = new SturdyFactoryBuilding();
building.printBuildQuality();
building.printColor();
building.paint("bright red");
building.printColor();
building.printFactoryOutput();
Is there a way I can achieve this, perhaps by having an 'isFactory' flag in the superclass.
Thanks.
I think you'll have to make a trade-off: Either you accept some anti-pattern or you open up you Building "interface" to act as an Adapter:
class Building implements Factory{
// the other building stuff
#Override
public void printFactoryOutput(){ /* NO OP */ }
}
Then you can call printFactoryOutput on all Buildings having no effect up to this point.
Since your Factory-implementations extend Building they automatically inherit the NOOP-Implementation. But since you override it:
class ShakyFactoryBuilding extends Building implements Factory{
ShakyFactoryBuilding(){
super();
}
#Override
public void printBuildQuality(){
println("The build quality is shaky");
}
#Override
public void printFactoryOutput(){
println("This factory makes slightly different stuff");
}
}
... you have the desired result.
Drawback is of course that all Buildings do have the printFactoryOutput visible. But that's the trade-off I was talking about. If this is not acceptable, you'll have to completely reconsider your design.
To make it clear that a Building that is not a Factory shall not be called that Method on, you could throw an UnsupportedOperationException in Building, but that would force try/catch blocks everywhere in your code. You could as well return a boolean: default=false and returning true if in fact a factory ... There are plenty possibilities.
You could also change your design to use composition over inheritance.
I think you're getting the message that this is a bad idea. It violates generally accepted object oriented design principles. That said, there are several ways to go about it, some less odious than others.
Just cast it
The simplest thing to do is something like this:
if (building instanceof Factory)
((Factory)building).printFactoryOutput();
You're checking to see whether it's a Factory, then invoking the Factory-specific method after casting. It's a straightforward (and therefore easily understood) way of implementing a bad design.
Make Building aware of Factory
This has issues in that there is currently no necessary relationship between Building and Factory, but such a relationship might help you along.
class Building {
// ...
Factory adaptToFactory() {
return null;
}
}
class SturdyFactoryBuilding ... {
// ...
#Override
Factory adaptToFactory() {
return this;
}
}
Similarly for ShakyFactoryBuilding.
Then you could write
Factory f = building.adaptToFactory();
if (f != null)
f.printFactoryOutput();
More general adapter
If you're doing a lot of this kind of thing, you could make it into a pattern that you apply wherever needed. (Eclipse, for example, uses adapters all over the place.)
interface Adaptable {
<T> T adapt(Class<T> clazz);
}
class Building implements Adaptable {
// ...
#Override
<T> T adapt(Class<T> clazz) {
if (clazz.isInstance(this)) {
return clazz.cast(this);
}
return null;
}
}
Then you'd write
Factory f = building.adapt(Factory.class);
if (f != null)
f.printFactoryOutput();
There are still more places to go with this, but this is far enough for this question, I think.
I'm working on a small game template, with a world comprised of nodes like so:
World
|--Zone
|----Cell
|------Actor
|------Actor
|--------Item
Where a World can contain multiple Zone objects, a Zone can contain multiple Cell objects, and so on.
Each of these implements the Node interface, which has a few methods like getParent, getChildren, update, reset and so on.
I want to be able to execute a given Task on a single node or recursively down the tree from a node (as specified by the Task).
To compound this issue, I would like this to be a "pluggable" system, meaning I want players/developers to be able to add new types to the tree on the fly. I had also considered casting from the base types:
public void doTask(Actor node)
{
if(!(node instanceof Goblin)) { return; }
Goblin goblin = (Goblin) node;
}
Initially I was drawn to use the Visitor Pattern to take advantage of double dispatch, allowing each routine (Visitor) to act according to the type of Node being visited. However, this caused a few complications, specifically when I want to add a new Node type to the tree.
As an alternative, I wrote a utility class that uses reflection to find the most specific method applicable to the Node.
My concern now is performance; since there will be a fairly large number of reflective lookups and calls, I'm worried that the performance of my game (which could have hundreds or thousands of these calls per second) will suffer.
Which seems to solve the problem of both patterns, but makes the code for each new Task uglier.
The way I see it, I have three options for allowing this dynamic dispatch (unless I'm missing something obvious/obscure, which is why I'm here):
Visitor Pattern
Pros
Double Dispatch
Performance
Clean Code in tasks
Cons
Difficult to add new Node types (impossible without modifying original code)
Ugly code during invocation of tasks
Dynamic Invocation using Reflection
Pros
Can add new Node types with abandon
Very customizable tasks
Clean Code in tasks
Cons
Poor performance
Ugly code during invocation of tasks
Casting
Pros
More performant than reflection
Potentially more dynamic than Visitor
Clean code during invocation of tasks
Cons
Code smell
Less performant than Visitor (no double dispatch, casting in each invocation)
Ugly code in tasks
Have I missed something obvious here? I'm familiar with many of the Gang of Four patterns, as well as the ones in Game Programming Patterns. Any help would be appreciated here.
To be clear, I'm not asking which of these is the "best". I'm looking for an alternative to these approaches.
So after some research into Java 8 Lambdas and how they can be constructed reflectively, I came up with the idea of creating a BiConsumer from the Method object I had obtained reflectively, with the first argument being the instance on which the method should be invoked and the second argument being the actual argument of the method:
private static <T, U> BiConsumer<T, U> createConsumer(Method method) throws Throwable {
BiConsumer<T, U> consumer = null;
final MethodHandles.Lookup caller = MethodHandles.lookup();
final MethodType biConsumerType = MethodType.methodType(BiConsumer.class);
final MethodHandle handle = caller.unreflect(method);
final MethodType type = handle.type();
CallSite callSite = LambdaMetafactory.metafactory(
caller,
"accept",
biConsumerType,
type.changeParameterType(0, Object.class).changeParameterType(1, Object.class),
handle,
type
);
MethodHandle factory = callSite.getTarget();
try {
//noinspection unchecked // This is manually checked with exception handling.
consumer = (BiConsumer<T,U>) factory.invoke();
}catch (ClassCastException e) {
LOGGER.log(Level.WARNING, "Unable to cast to BiConsumer<T,U>", e);
}
return consumer;
}
Once this BiConsumer has been created, it is cached in a HashMap using the parameter type and method name as a key. It can then be invoked like so:
consumer.accept(nodeTask, node);
This method of invocation almost entirely eliminates the invocation overhead incurred by reflection, but it does have a couple of issues/constraints:
Because of the use of BiConsumer, only one parameter may be passed into the method (the first argument to the accept method must be the instance that should have the method invoked on it).
This is fine for my purposes, I only want to pass one argument anyway.
There is a non-trivial performance overhead when invoking a method with parameter types that haven't been seen before, as it must first be searched for reflectively.
Again, for my purposes this is OK; the number of acceptable node types will not be very large and will be quickly cached as they are seen. After this first "discovery" of the appropriate method for combinations of parameter types, the overhead is very small (constant, I believe, as it's a simple HashMap lookup).
Requires Java 8 (which I was using already anyway)
I could clarify this code a bit by using a custom functional interface (something like an Invoker class instead of Java's BiConsumer) but as of right now it does exactly what I want with the performance I want.
I think that if you cannot have a static factory class then it is a tough problem. If a static factory is allowed, then perhaps this short example might provide some ideas.
This sort of approach allows for run-time insertion of INode instances into the tree (WorldNode), however, it doesn't answer how these concrete INodes are created. I would hope you would have some kind of factory pattern.
import java.util.Vector;
public class World {
public static void main(String[] args) {
INode worldNode = new WorldNode();
INode zoneNode = new ZoneNode();
zoneNode.addNode(new GoblinNode());
zoneNode.addNode(new GoblinNode());
zoneNode.addNode(new GoblinNode());
zoneNode.addNode(new GoblinNode());
worldNode.addNode(zoneNode);
worldNode.addNode(new ZoneNode());
worldNode.addNode(new ZoneNode());
worldNode.addNode(new ZoneNode());
worldNode.runTasks(null);
}
}
interface INode {
public void addNode(INode node);
public void addTask(ITask node);
public Vector<ITask> getTasks();
public void runTasks(INode parent);
public Vector<INode> getNodes();
}
interface ITask {
public void execute();
}
abstract class Node implements INode {
private Vector<INode> nodes = new Vector<INode>();
private Vector<ITask> tasks = new Vector<ITask>();
public void addNode(INode node) {
nodes.add(node);
}
public void addTask(ITask task) {
tasks.add(task);
}
public Vector<ITask> getTasks() {
return tasks;
}
public Vector<INode> getNodes() {
return nodes;
}
public void runTasks(INode parent) {
for(ITask task : tasks) {
task.execute();
}
for(INode node : nodes){
node.runTasks(this);
}
}
}
class WorldNode extends Node {
public WorldNode() {
addTask(new WorldTask());
}
}
class WorldTask implements ITask {
#Override
public void execute() {
System.out.println("World Task");
}
}
class ZoneNode extends Node {
public ZoneNode() {
addTask(new ZoneTask());
}
}
class ZoneTask implements ITask {
#Override
public void execute() {
System.out.println("Zone Task");
}
}
class GoblinNode extends Node {
public GoblinNode() {
addTask(new GoblinTask());
}
}
class GoblinTask implements ITask {
#Override
public void execute() {
System.out.println("Goblin Task");
}
}
Output:
World Task
Zone Task
Goblin Task
Goblin Task
Goblin Task
Goblin Task
Zone Task
Zone Task
Zone Task
The reflection idea is fine - you'll just need to cache the lookup result based on argument types.
The visitor pattern can be expanded by user program. For example, given the classic Node and Visitor definitions in visitor pattern, user can define
MyNode, MyVisitor
interface MyVisitor extends Visitor
{
void visit(MyNode m);
void visit(MyNodeX x);
...
}
interface MyNode extends Node
{
#Override default void accept(Visitor visitor)
{
if(visitor instanceof MyVisitor)
acceptNew((MyVisitor) visitor);
else
acceptOld(visitor);
}
void acceptNew(MyVisitor visitor);
void acceptOld(Visitor visitor);
}
class MyNodeX implements MyNode
{
#Override public void acceptNew(MyVisitor visitor)
{
visitor.visit(this);
}
#Override public void acceptOld(Visitor visitor)
{
visitor.visit(this);
}
}
// problematic if MyNodeX extends NodeX; requires more thinking
In general, I don't like visitor pattern; it is quite ugly, rigid, and intrusive.
Basically, the problem is that given a node type and a task type, lookup a handler. We can solve this by a simple map of (node,task)->handler. We can invent some APIs for bind/lookup handlers
register(NodeX.class, TaskY.class, (x,y)->
{
...
});
or with anonymous class
new Handler<NodeX, TaskY>() // the constructor registers `this`
{
#Override public void handle(NodeX x, TaskY y)
...
To invoke a task on a node,
invoke(node, task);
// lookup a handler based on (node.class, task.class)
// if not found, lookup a handler on supertype(s). cache it by (node.class, task.class)
If you are looking for performance - the visitor pattern is the way to go. I personally would't even have come up with reflection as a solution to this, as it seems unreal and overcomplicated. Casting works, but in an OO environment it is usually considered code smell and should be avoided (for example with the visitor pattern).
Another important aspect is readability vs writability: The visitor pattern might be a bit more work and requires more maintenance when adding nodes, but it is definitely easier to read and usually easier to understand as well. Reflection is in both aspects a no-go, and casts are, again, code smell.
I am trying to find a way to bypass the use of instanceof. I've created a class Item which has multiple subclasses like WeaponItem and BodyItem. Now I would like to make to do a call such as equip(Item) and it should determine by itself which overloaded function it should call such as equip(BodyItem).
Is there a way to bypass the use of instanceof for this case and what would you recommend? I've heard that in most cases using instanceof is bad practice and therefor I want to know what the alternatives are.
Code:
inv.equip(it); // inv = inventory object, it = Item
An example of equip function within inventory class how I preferably want it
public void equip(HelmItem it)
{
if (it != this.getHelm())
{
this.setHelm(it);
}
}
How I had it before:
public void equip(Item it)
{
if (it instanceof WeaponItem)
{
if (it != this.getWeapon())
{
this.setWeapon((WeaponItem) it);
}
} etc for all subclasses of item
}
Indeed, this could be solved with a visitor pattern.
However, it does not have to be a full-blown visitor, but a simplified variation of it. You could pass the inventory to the item and let the item do whatever it wants with it:
abstract class Item {
public abstract void equip(Inventory inv);
}
class HelmItem extends Item {
#Override
public void equip(Inventory inv) {
inv.setHelm(this);
}
}
class WeaponItem extends Item {
#Override
public void equip(Inventory inv) {
inv.setWeapon(this);
}
}
Then you can just call:
it.equip(inv)
without the instanceof operator.
Why not put the method in the Item concrete class, and it can equip itself? It's a little counter intuitive but it would solve your problem.
public class SomeConcreteItem extends Item {
public void equip(Body body) {
// Just an example.
body.getSections().get(0).equip(this);
}
}
That way, the concrete implementation knows how to equip itself and the classes that use it don't care. You can reference it by the Item superclass and provided that the Item superclass has an abstract method public void equip(Body body);, then you don't ever need to know about the concrete implementation and, therefore, no need for the instanceof operator.
A Note on Introducing a Design Pattern
You should be careful about introducing Design Patterns. People have a bad habit of leaping straight to a complicated pattern to solve a problem, when really something simpler and (in my opinion) more elegant is available.
I have the following code in which I have a parent class and its child. I am trying to determine how the code benefits from using polymorphism.
class FlyingMachines {
public void fly() {
System.out.println("No implementation");
}
}
class Jet extends FlyingMachines {
public void fly() {
System.out.println("Start, Taxi, Fly");
}
public void bombardment() {
System.out.println("Throw Missile");
}
}
public class PolymorphicTest {
public static void main(String[] args) {
FlyingMachines flm = new Jet();
flm.fly();
Jet j = new Jet();
j.bombardment();
j.fly();
}
}
What is the advantage of polymorphism when both flm.fly() and j.fly() give me the same answer?
In your example, the use of polymorphism isn't incredibly helpful since you only have one subclass of FlyingMachine. Polymorphism becomes helpful if you have multiple kinds of FlyingMachine. Then you could have a method that accepts any kind of FlyingMachine and uses its fly() method. An example might be testMaxAltitude(FlyingMachine).
Another feature that is only available with polymorphism is the ability to have a List<FlyingMachine> and use it to store Jet, Kite, or VerySmallPebbles.
One of the best cases one can make for using polymorphism is the ability to refer to interfaces rather than implementations.
For example, it's better to have a method that returns as List<FlyingMachine> rather than an ArrayList<FlyingMachine>. That way, I can change my implementation within the method to a LinkedList or a Stack without breaking any code that uses my method.
What is the advantage of polymorphism when both flm.fly() and j.fly()
give me the same answer?
The advantage is that
FlyingMachines flm = new Jet();
flm.fly();
returns
"Start, Taxi, Fly"
instead of
"No implementation"
That's polymorphism. You call fly() on an object of type FlyingMachine and it still knows that it is in fact a Jet and calls the appropriate fly() method instead of the wrong one which outputs "No implementation".
That means you can write methods that work with objects of type FlyingMachine and feed it with all kinds of subtypes like Jet or Helicopter and those methods will always do the right thing, i.e. calling the fly() method of the appropriate type instead of always doing the same thing, i.e. outputting "No implementation".
Polymorphism
Polymorphism is not useful in your example.
a) It gets useful when you have different types of objects and can write classes that can work with all those different types because they all adhere to the same API.
b) It also gets useful when you can add new FlyingMachines to your application without changing any of the existing logic.
a) and b) are two sides of the same coin.
Let me show how.
Code example
import java.util.ArrayList;
import java.util.List;
import static java.lang.System.out;
public class PolymorphismDemo {
public static void main(String[] args) {
List<FlyingMachine> machines = new ArrayList<FlyingMachine>();
machines.add(new FlyingMachine());
machines.add(new Jet());
machines.add(new Helicopter());
machines.add(new Jet());
new MakeThingsFly().letTheMachinesFly(machines);
}
}
class MakeThingsFly {
public void letTheMachinesFly(List<FlyingMachine> flyingMachines) {
for (FlyingMachine flyingMachine : flyingMachines) {
flyingMachine.fly();
}
}
}
class FlyingMachine {
public void fly() {
out.println("No implementation");
}
}
class Jet extends FlyingMachine {
#Override
public void fly() {
out.println("Start, taxi, fly");
}
public void bombardment() {
out.println("Fire missile");
}
}
class Helicopter extends FlyingMachine {
#Override
public void fly() {
out.println("Start vertically, hover, fly");
}
}
Explanation
a) The MakeThingsFly class can work with everything that is of type FlyingMachine.
b) The method letTheMachinesFly also works without any change (!) when you add a new class, for example PropellerPlane:
public void letTheMachinesFly(List<FlyingMachine> flyingMachines) {
for (FlyingMachine flyingMachine : flyingMachines) {
flyingMachine.fly();
}
}
}
That's the power of polymorphism. You can implement the open-closed-principle with it.
The reason why you use polymorphism is when you build generic frameworks that take a whole bunch of different objects with the same interface. When you create a new type of object, you don't need to change the framework to accommodate the new object type, as long as it follows the "rules" of the object.
So in your case, a more useful example is creating an object type "Airport" that accepts different types of FlyingMachines. The Airport will define a "AllowPlaneToLand" function, similar to:
//pseudocode
void AllowPlaneToLand(FlyingMachine fm)
{
fm.LandPlane();
}
As long as each type of FlyingMachine defines a proper LandPlane method, it can land itself properly. The Airport doesn't need to know anything about the FlyingMachine, except that to land the plane, it needs to invoke LandPlane on the FlyingMachine. So the Airport no longer needs to change, and can continue to accept new types of FlyingMachines, be it a handglider, a UFO, a parachute, etc.
So polymorphism is useful for the frameworks that are built around these objects, that can generically access these methods without having to change.
let's look at OO design first, inheritance represents a IS-A relationship, generally we can say something like "let our FlyingMachines fly". every specific FlyingMachines (sub class) IS-A FlyingMachines (parent class), let say Jet, fits this "let our FlyingMachines fly", while we want this flying actually be the fly function of the specific one (sub class), that's polymorphism take over.
so we do things in abstract way, oriented interfaces and base class, do not actually depend on detail implementation, polymorphism will do the right thing!
Polymorphism (both runtime and compile time) is necessary in Java for quite a few reasons.
Method overriding is a run time polymorphism and overloading is compile time polymorphism.
Few of them are(some of them are already discussed):
Collections: Suppose you have multiple type of flying machines and you want to have them all in a single collection. You can just define a list of type FlyingMachines and add them all.
List<FlyingMachine> fmList = new ArrayList<>();
fmList.add(new new JetPlaneExtendingFlyingMachine());
fmList.add(new PassengerPlanePlaneExtendingFlyingMachine());
The above can be done only by polymorphism. Otherwise you would have to maintain two separate lists.
Caste one type to another : Declare the objects like :
FlyingMachine fm1 = new JetPlaneExtendingFlyingMachine();
FlyingMachine fm2 = new PassengerPlanePlaneExtendingFlyingMachine();
fm1 = fm2; //can be done
Overloading: Not related with the code you gave, But overloading is also another type of polymorphism called compile time polymorphism.
Can have a single method which accepts type FlyingMachine handle all types i.e. subclasses of FlyingMachine. Can only be achieved with Polymorphism.
It doesn't add much if you are going to have just Jets, the advantage will come when you have different FlyingMachines, e.g. Aeroplane
Now that you've modified to include more classes, the advantage of polymorphism is that abstraction from what the specific type (and business concept) of the instance you receive, you just care that it can fly
Polymorphism can also help our code to remove the "if" conditionals which is intended to produce production level code because removing conditionals will increase the code readability and helps us to write better unit test cases, we know for "n" if cases there comes n!(n factorial) possibilities.
Let us see how
if you have class FlyingMachine and which takes a string in the constructor defining the type of FlyMachine as below
class FlyingMachine{
private type;
public FlyingMachine(String type){
this.type = type;
}
public int getFlyingSpeedInMph {
if(type.equals("Jet"))
return 600;
if(type.equals("AirPlane"))
return 300;
}
}
We can create two instances of FlyingMachine as
FlyingMachine jet = new FlyingMachine("Jet");
FlyingMachine airPlane = new FlyingMachine("AirPlane");
and get the speeds using
jet.fylingSpeedInMph();
airPlane.flyingSpeedInMph();
But if you use polymorphism you are going to remove the if conditions by extending the generic FlyMachine class and overriding the getFlyingSpeedInMph as below
class interface FlyingMachine {
public int abstract getFlyingSpeedInMph;
}
class Jet extends FlyingMachine {
#Override
public int getFlyingSpeedInMph(){
return 600;
}
}
class Airplane extends FlyingMachine {
#Override
public int getFlyingSpeedInMph(){
return 600;
}
}
Now you can get the flying speeds as below
FlyingMachine jet = new Jet();
jet.flyingSpeed();
FlyingMachine airPlane = new AirPlane();
airPlane.flyingSpeed();
Both flm.fly() and j.fly() give you the same answer because of the type of the instance is actually the same, which is Jet, so they are behave the same.
You can see the difference when you:
FlyingMachines flm = new FlyingMachines();
flm.fly();
Jet j = new Jet();
j.bombarment();
j.fly();
Polymorphism is define as same method signature with difference behaviour. As you can see, both FlyingMachines and Jet have method fly() defined, but the method is implemented differently, which consider as behave differently.
See
aa
Polymorphism
Let's add one more class in this, It help's you to understand use of polymorphism..
class FlyingMachines {
public void fly() {
System.out.println("No implementation");
}
}
class Jet extends FlyingMachines {
public void fly() {
System.out.println("Start, Jet, Fly");
}
}
class FighterPlan extends FlyingMachines {
public void fly() {
System.out.println("Start, Fighter, Fight");
}
}
public class PolymorphicTest {
public static void main(String[] args) {
FlyingMachines flm = new Jet();
flm.fly();
FlyingMachines flm2 = new FighterPlan();
flm2.fly();
}
}
Output:
Start, Jet, Fly
Start, Fighter, Fight
Polymorphism gives you benefits only if you need Polymorphism.
It's used when an entity of your conceptual project can be seen as the specialization of another entity.
The main idea is "specialization".
A great example stands in the so called Taxonomy,for example applied to living beings.
Dogs and Humans are both Mammals.
This means that, the class Mammals group all the entities that have some properties and behaviors in common.
Also, an ElectricCar and a DieselCar are a specialization of a Car.
So both have a isThereFuel() because when you drive a car you expect to know if there's fuel enough for driving it.
Another great concept is "expectation".
It's always a great idea to draw an ER (entity relationship) diagram of the domain of your software before starting it.
That's because your are forced to picture which kind of entities are gonna be created and, if you're able enough, you can save lot of code finding common behaviors between entities.
But saving code isn't the only benefit of a good project.
You might be interested in finding out the so called "software engineering" that it's a collection of techniques and concepts that allows you to write "clean code" (there's also a great book called "Clean code" that's widely suggested by pro-grammes).
The good reason for why Polymorphism is need in java is because the concept is extensively used in implementing inheritance.It plays an important role in allowing objects having different internal structures to share the same external interface.
polymorphism as stated clear by itself, a one which mapped for many.
java is a oops language so it have implementation for it by abstract, overloading and overriding
remember java would not have specification for run time polymorphism.
it have some best of example for it too.
public abstract class Human {
public abstract String getGender();
}
class Male extends Human
{
#Override
public String getGender() {
return "male";
}
}
class Female extends Human
{
#Override
public String getGender() {
return "female";
}
}
Overriding
redefine the behavior of base class.
for example i want to add a speed count int the existing functionality of move in my base Car.
Overloading
can have behavior with same name with different signature.
for example a particular president speaks clear an loud but another one speaks only loud.
Here, for this particular code, there is no need of polymorphism.
Let's understand why and when we need polymorphism.
Suppose there are different kinds of machines (like car, scooter, washing machine, electric motor, etc.) and we know that every machine starts and stops. But the logic to start and stop a machine is different for each machine. Here, every machine will have different implementations to start and stop. So, to provide different implementations we need polymorphism.
Here we can have a base class machine with start() and stop() as its methods and each machine type can extend this functionality and #Override these methods.