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.
Related
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.
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.
I'm developing an application which builds on a class written by another developer (for which I do not have the source).
I wish to use all of the functionality of said class but also to extend it with additional functionality. Ordinarily to achieve this I would have defined an interface (MyInterface) and have extended the external class (TheirClass) from my own (MyClass) while implementing MyInterface.
public interface TheirClassInterface {
public void theirMethod1();
public void theirMethod2();
}
public class TheirClass implements TheirClassInterface {
public void theirMethod1() { ... }
public void theirMethod2() { ... }
}
public class TheirOtherClass {
public void theirOtherMethod1(TheirClassInterface o) { ... }
}
public interface MyInterface() {
public void myMethod1();
}
public class MyClass extends TheirClass implements MyInterface {
public void myMethod1() { ... }
}
public class MyNewClass extends MyClass {
public void MyNewClassMethod() { ... }
}
The problem is complicated by the fact that:
I now wish to create a new class (MyNewClass) which adds additional functionality to MyClass but I don't want my code to be dependent on TheirClass.
I wish to be able to use my class as a parameter to the method of TheirOtherClass.
To combat this I refactored my code to instead use composition over inheritance and implementing TheirClassInterface. This works but requires me to implement many methods and delegate them to theirClassObject (in reality TheirClassInterface contains a very large number of methods).
public interface TheirClassInterface {
public void theirMethod1();
public void theirMethod2();
}
public class TheirClass implements TheirClassInterface {
public void theirMethod1() { ... }
public void theirMethod2() { ... }
}
public class TheirOtherClass {
public void theirOtherMethod1(TheirClassInterface o) { ... }
}
public interface MyInterface() {
public void myMethod1();
}
public class MyClass implements TheirClassInterface, MyInterface {
private TheirClass theirClassObject;
public void myMethod1() { ... }
public void theirMethod1() { theirClassObject.theirMethod1(); }
public void theirMethod2() { theirClassObject.theirMethod2(); }
}
public class MyNewClass extends MyClass {
public void MyNewClassMethod() { ... }
}
My question is whether my approach is appropriate in this case and whether it could be improved upon as it seems to me that my code uses an excessive amount of delegation to get the job done.
Many thanks for any guidance anyone can give on this.
Danny
First, as java is a strongly-typed single inheritance language, you cannot escape the delegation.
But you can avoid having to write a lot of delegation CODE, by using a dirty little trick with Proxies and reflection.
Code follows
public interface Interface1 {
void m1();
}
public interface Interface2 {
void m2();
}
public class Class1 implements Interface1 {
public void m1() {
System.out.println(1);
}
}
public class Class2 implements Interface2 {
public void m2() {
System.out.println(2);
}
}
public interface MixinInterface extends Interface1, Interface2 {
}
And this is how the magic happens
package j.with.pseudo.multiple.inheritance;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class MixinBuilder {
public static Object buildMixed(Class _interface, Object... impls){
InvocationHandler h = new MixinHandler(_interface.getInterfaces(), impls);
return Proxy.newProxyInstance(MixinBuilder.class.getClassLoader(),
new Class[]{_interface}, h);
}
public static void main(String[] args) {
Class1 o1 = new Class1();
Class2 o2 = new Class2();
MixinInterface almost_like_multiple_inheritance_guy =
(MixinInterface) buildMixed(MixinInterface.class, o1, o2);
almost_like_multiple_inheritance_guy.m1();
almost_like_multiple_inheritance_guy.m2();
}
private static class MixinHandler implements InvocationHandler{
private Class[] interfaces;
private Object[] impls;
public MixinHandler(Class[] interfaces, Object[] impls) {
this.interfaces = interfaces;
this.impls = impls;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
int i=0;
for(Class _interface : interfaces){
if(method.getDeclaringClass().isAssignableFrom(_interface)){
return method.invoke(impls[i], args);
}
i++;
}
// TODO Auto-generated method stub
throw new RuntimeException("Method not found: "+method);
}
}
}
Pretty cool huh? :-)
You can't not-depend on a class if you're extending it; it's like having a definition of Human, which does not depend on the definition of Mammal, your optinos are to rewrite everything in the parent, or depend on it.
Many thanks for the answers so far. I've come up with a solution which I think seems reasonable and allows me to fully encapsulate the foreign class.
At the moment I've returned to the method discussed in the first block of code (repeated and extended below) and am now implementing my MyInterface interface for MyNewClass and delegating all interface operations to a composed object. The object to delegate to is decided at runtime by calling a static method on a Factory.
public interface TheirClassInterface {
public void theirMethod1();
public void theirMethod2();
}
public class TheirClass implements TheirClassInterface {
public void theirMethod1() { ... }
public void theirMethod2() { ... }
}
public class TheirOtherClass {
public void theirOtherMethod1(TheirClassInterface o) { ... }
}
public interface MyInterface() {
public void myMethod1();
}
public class MyClass extends TheirClass implements MyInterface {
public void myMethod1() { ... }
}
public class MyNewClass implements MyInterface {
private MyInterface myObject;
public MyNewClass() {
myObject = MyClassFactory.createMyClass();
}
public void myMethod1() {
myObject.myMethod();
}
public void MyNewClassMethod() { ... }
}
Once again, thanks for the ideas. I'm now going to look into them all and see if I can use them to improve my code.
Cheers,
Danny
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.
If I have a class that I would like to customise by overriding one if its methods the only I can do this is by using inheritance (sub-classing and overriding method) ? Is it possible to use composition in some way to achieve same goal ?
Yes, you can use delegation. Instead of deriving from Foo in the example below, Bar contains a Foo and delegates to it where it chooses.
interface SomeMethods {
void doSomething();
void doSomethingElse();
}
class Foo implements SomeMethod {
public void doSomething() { // implementation }
public void doSomethingElse() { // implementation }
}
class Bar implements SomeMethod {
private final Foo foo = new Foo();
public void doSomething() { foo.doSomething(); }
public void doSomethingElse() { // do something else! }
}
Using composition instead of inheritance is a design choice.
Either your class has been designed with inheritance in mind (i.e. it provides non-final public and protected methods, intended to be overridden by subclasses), or it has been designed with composition or delegation in mind (by using the strategy pattern, for example).
If the class has not been designed for customization at all, you might be able to customize it using inheritance, but not using a composition/delegation mechanism.
Sure. You can use the following patterns.
Simple overriding of method method
Template method pattern
class Base {
public void foo() {
// do something
bar();
// do something
}
protected abstract void bar();
}
class Child {
protected void bar() {
// do something.
}
}
Delegation
class Base {
private Runnable r;
protected Base(Runnable r) {
this.r = r;
}
public void foo() {
r.run();
}
}
class Child extends Base {
Child() {
super(new Runnable() { /* implementation */})
}
}