I need some useful suggestion on design pattern for the following problem in Java.
I have three classes:
class A extends X implement Y {
doA()
}
class B extends X implement Y {
doB()
}
class C extends X implement Y {
doC()
}
Now I would like create a class D that should reuse methods doA, doB and doC of classes A, B and C respectively.
Can anyone suggest a design for the above problem?
I think you need to use paradigm "Prefer composition over inheritance". Design class D that includes instances of A, B, C and call their methods as necessary. In addition, D can implement Y if necessary and delegate corresponding API calls to either A or B or C.
This isn't directly possible as it stands.
Your best bet, if your design will allow, is to recreate X as an interface, and the others as interfaces that extend X. That will allow D to implement all the others.
Failing that, you might (depending on what you're trying to do) get away with having D hold a private instance of A, B and C, and then get it to delegate the methods you mention to those instances. But bear in mind that you'll have three different X instances if you do it like that.
The right answer is probably that your class hierarchy is already not quite what it should be! But there's not enough detail in the question to be certain.
You can try something like this:
class A extends X implement Y{
doA()
}
class B extends X implement Y{
doB()
}
class C extends X implement Y{
doC()
}
interface Delegator {
doSomething();
}
class DBuider {
public DBuider with(Delegator d) {
// create chain and store it
return this;
}
Chain build() {
// return new D with resulted chain
}
class Chain {
Delegator del;
Chain next;
}
}
class D implements Y {
Chain c;
static DBuilder create() {
return new DBuilder();
}
doD() {
Chain t = c;
while (t != null) {
t.del.doSomething();
t = t.next;
}
}
}
----- Usage -----
D.create().with(() -> new A().doA()).with(() -> new B().doB()).build().doD();
You could compose your new class D from your existing classes:
class D {
private A a = new A();
private B b = new B();
private C c = new C();
public void foo() {
this.a.doA();
this.b.doB();
this.c.doC();
}
}
Without knowing all the details, this feels like a composition problem.
Class D
{
private A _a = new A();
private B _b = new B();
private C _c = new C();
doA()
{
_a.doA();
}
doB()
{
_b.doB();
}
doC()
{
_c.doC();
}
}
This may or may not actually be appropriate based on what you are trying to do.
Related
I came across the following Java code that uses generics and inheritance. I truly do not understand what the following snippet does:
class A<B extends A<B>> {
...
}
What does this code do?
(I got this from DBMaker in MapDB)
It is almost clear and the question actually conists in two parts:
1) why B extends A?
2) why A inside B extends A<B> has generic type B?
Answers for these parts will be:
1) In particular example this class (A) is builder class (called DBMaker), so most of its methods return some type, which extends this builder's class type. This explains, why B should extend A class.
2) But, actualy, if we will hide for the second part ...extends A<B>, we will receive just class A<B>. So A has type variable of type B. That is why in ...extends A<B> A is marked as type A having type variable B.
This tells that A needs derived definitions to be able to do some work:
public abstract class A<T extends A<T>> {
protected T instance;
T getOne() {
return instance;
}
}
public class B extends A<B> {
public B() {
instance = this;
}
}
public static void test() {
B b = new B();
b.getOne();
}
This is most commonly used in interface definitions, where one wants to explicitly use instances of classes implementing an interface in return types or in arguments and not the interface itself:
public interface TimeSeries<T extends TimeSeries<T>> {
T join(T ts);
}
public class DoubleTimeSeries implements TimeSeries<DoubleTimeSeries> {
#Override
public DoubleTimeSeries join(DoubleTimeSeries ts) {
return null;
}
}
So I did some tests to figure this one out, and here is my test cases to see how one could use such a generic case:
public class A<B extends A<B>> {
int x = 10;
B test;
void printX() {
System.out.println(x);
}
void setB(B b) {
test = b;
}
void printB() {
System.out.println(test);
}
}
public class B extends A<B> {
}
public class Run {
public static void main(String[] args) {
A<B> test = new A<B>();
B myB = new B();
test.printX();
test.setB(myB);
test.printB();
myB.printB();
}
}
I hope the code might be self explanatory. If not leave a comment and I will try and explain what is going on. Look at the last line, myB.printB(), here we will get a null, because B has not yet been set for myB, but only for test. This demonstrates that we can have an infinite recursion into classes of B inside A (and inside B for that matter).
we can say:
myB.test.printB();
This will get an error (null pointer), but shows that we now have access to test in the A class from B, and we can go as deep as we want recursively with as many cases as we like. So the A class kind of functions as a wrapper of infinitely many B classes. Does this make sense?
This makes it easier when defining method return types such as this:
class A<B extends A<B>> {
public B getMe(){
return (B) this;
}
}
This tells Java compiler that you are in getMe() method returning a subclass of class A.
class C extends A<C> {
}
C c = new C();
c.getMe(); //returns C
I have the following classes:
public abstract class A implements C {
...
}
public abstract class B extends A {
method();
}
But when I try to do the following
A a = null;
A a = new A();
((B) a).method();
I receive a ClassCastException, does anyone have a solution?
B extends A, but A doesnt extend B.
everything A has B has, but A cant do the stuff declared in B
An instance of B is an instance of A, but an instance of A is not necessarily a B. Similar to saying "all circles are shapes, but not all shapes are circles".
You can't do what you are trying to do. That's why you get the exception.
I think what you want here is a constructor to take and A object and make a larger B object out of it which has the included method (which A does not have). But that doesn't make a whole lot of sense. Cant think for the life of me why you would want to do this in practice, and wouldn't just build the B object to start with.
public abstract class A implements C {
...
}
public abstract class B extends A {
public B(A child){
//Construct a B out of A here
}
public void method();
}
Then
A a = null;
A a = new A();
new B(a).method();
I have a number of classes, please allow me to introduce them and then ask my question at the end:
I have a container class which contains two objects in a composite relationship:
public class Container{
A a;
B b;
public someMethod(){
a.getC().myMethod(b);
}
}
A and B are superclasses (or Interfaces), with subtypes that can also be the type held in the composite relationship.
A contains a member of (interface) type C:
public class A{
C c;
}
public interface C{
public void myMethod(B b);
}
public class D implements C{
public void myMethod(B b){
//This code will modify the state of object b, in class Container.
b.changeState();
}
}
public class E implements C{
public void myMethod(B b){
//This code will modify the state of object b, in class Container.
b.changeState();
}
}
My problem is that I wish to modify the state of object b from a method starting in the container class, which eventually calls code down the hierarchy, to classes D and E- calling myMethod() via dynamic binding. I want to do this because I am going to use polymorphism to run the correct myMethod() (depending on whether the type of object is D or E) and I wish to do this, rather than write IF statements.
So my problem is that it seems very bad continually passing the instance of object b down the class hierarchy to myMethod, so that I can run b-specific code to modify the state of b. Is there anything else I can do to modify b from d and e (collectively known as c)?
I can get this to work using just interfaces but without using generics- but when I added generics i had problems with types and that made me start to think if my whole design was flawed?
EDIT: I could probably do this easily just by using IF statements- but I wanted an elegant solution using polymorphism of classes D and E.
First of all, if I understood your question correctly, no instance of B is being "passed down" in your code. Dynamic dispatch will simply cause the myMethod() implementation in the actual type of a to be called with an instance of B as argument.
While it may be tedious to have to write the argument explicitly every time you implement myMethod(), there's nothing wrong with it.
The alternative is to give each subclass/implementation of A an attribute of type B. In this case, however, you would have to pass your B instance down the chain of constructors to the class that actually has your B attribute.
Your code would become:
public class A{
C c;
public A(C c) {
this.c = c;
}
public interface C{
public void myMethod(B b);
}
public abstract class CC {
protected B b;
public CC(B b) {
this.b = b;
public class D extends CC implements C {
public D(B b) {
super(b);
}
public void myMethod(){
b.changeState();
}
}
public class E extends CC implements C {
public E(B b) {
super(b);
}
public void myMethod(){
b.changeState();
}
}
And then somewhere, e.g. in Container's constructor:
b = new B();
a = new A(new E(b));
You could pass the instance of B to the constructor of E. (or use a setter). That poses issues in itself, but at least it avoids having to pass B down every time you call myMethod(), which now needs no arguments.
e.g.
somewhere inside B
E myE = new E(this);
and, inside E
final B myB;
public E(B myHigherLevelThing) {
this.myB = myHigherLevelThing;
}
public void myMethod() {
myB.changeState();
}
Use the most general interface for the declarations, I'm a little confused about your full hierarchy so there may be room for improvement there...
Lets say class C and D extend class B which extends class A
I have a methods in class E that I want to be able to use either an object C or object D in. I know that class A provides all the methods that I need. How can I go about writing a method that lets me pass either a object C or object D as a parameter?
Am I right in thinking I need to make a generic class? If so does anyone have specific examples that are closer to what I need that this which only seems to tell me how to use the existing collection class?
class A {
public String hello(){return "hello";}
}
class B extends A{}
class C extends B{}
class D extends B{}
The method hello is available in all subclasses B,C and D.
So in E, do something like:
private void test() {
System.out.println(hello(new A()));
System.out.println(hello(new B()));
System.out.println(hello(new C()));
System.out.println(hello(new D()));
}
public String hello(A a) {
return a.hello();
}
and you can pass instances of A,B,C or D
BTW - generics are not necessary in this scenario (as far as I understood it)
If C and D have A as their common ancestror and A provides all needed methods, then your method should simply take an instance of A as a parameter. You do not need a generic method, unless I misunderstood your question.
public void doSomething(A input) {
input.methodInA();
input.secondMethodInA();
...
}
Polymorphism will run an possible overridden code implement in C or D, you don't need to do anything other than call the method.
class A {
}
class B extends A {
}
class C extends B {
}
class D extends B {
}
class E {
public void test ( A a ) {
// c or d will work fine here
}
}
I recently fumbled into a problem with an API and an implementation where the following type of code appeared:
public abstract class A {
public A sum(A a) {
System.out.println("A.sum(A) called");
return null;
}
}
The implementation is a simple class:
public class B extends A {
public B sum(B b) {
System.out.println("B.sum(B) called");
return null;
}
}
When it comes to using it I write:
public class Main {
public static void main(String[] args) {
B b = new B();
A basa = new B();
b.sum(b);
basa.sum(b);
basa.sum(basa);
}
}
Which results in:
B.sum(B) called
A.sum(A) called
A.sum(A) called
I understand that B's sum does not override A's sum as its signature is different, but I'd like to provide an efficient implementation of sum for objects of effective type B. I think such design is quite classical and I would like to know how I should design my API and implementation so that it is efficient.
Of course I could provide sum(A a) in class B and check if b is an instanceof B before calling either sum(B b) or super, but I thought that instanceof was to be avoided for efficiency reasons. (if it is inefficient, it may be even less efficient with my abstract implementation)
instanceof can usually be avoided by using the visitor pattern. Depending on your needs, it may or may not be an overkill. It's flexible but quite verbose. In the example below I removed abstract from A to illustrate how it works with different types.
The trick is that when an object is asked to visit a visitor, the object itself chooses the correct accept method in the visitor. The "instanceof"-check is resolved through polymorphism. (I doubt that it's more efficient than an instanceof though.)
interface Visitor {
public A accept(A a);
public B accept(B b);
}
class A {
public A sum(A a) {
System.out.println("A.sum(A) called");
return null;
}
public A visit(Visitor sv) {
return sv.accept(this);
}
}
class B extends A {
public B sum(B b) {
System.out.println("B.sum(B) called");
return null;
}
public B visit(Visitor sv) {
return sv.accept(this);
}
}
public class Test {
public static void main(String[] args) {
A a = new A();
B b = new B();
A basa = new B();
a.visit(new SumVisitor(b)); // a.sum(b);
b.visit(new SumVisitor(b)); // b.sum(b);
basa.visit(new SumVisitor(b)); // basa.sum(b);
basa.visit(new SumVisitor(basa)); // basa.sum(basa);
}
static class SumVisitor implements Visitor {
A arg;
SumVisitor(A arg) { this.arg = arg; }
public A accept(A a) { return a.sum(arg); }
public B accept(B b) { return b.sum(arg); }
}
}
Output:
A.sum(A) called
B.sum(B) called
B.sum(B) called
B.sum(B) called
Disclamer; It was a while ago I wrote a visitor, so please correct me if I have any bugs in this (almost untested) code snippet. Or better, edit the post yourself and improve it :)
Since B instances can be summed with A instances using myA.sum(myB), you should be able to change B's definition of sum so that it does override, unless of course sum is a placeholder and isn't something that should be commutative.
UPDATE:
If this is insufficient, you could start getting fancy with generics. Here's a rough pass at what I mean:
public abstract class A {
public <T extends A> T sum(T a) {
System.out.println("A.sum(A) called");
return null;
}
public static void main(String args[]) {
B b = new B();
b.sum(b);
A basa = new B();
basa.sum(b);
basa.sum(basa);
}
public static class B extends A {
#Override
public <T extends A> T sum(T b) {
System.out.println("B.sum(B) called");
return null;
}
}
}
#aioobe is right that the generally accepted work-around is to use the Visitor pattern. I'm offering these as less complete but less verbose alternatives.
So, what makes you think instanceof is slow? It's used in several places in the JDK where they want to provide a "fast path" for certain well-known implementations of an abstract class or interface. The usual advice applies here: "Test, don't guess."