iamMobile
iamMobile

Reputation: 969

Effective design for related classes that use unrelated classes

I have following situation and would like to know the best way to design my solution

public abstract class A {
  public abstract A getHelper();
  public abstract void launchHandle();  
  public static A initHelper(String condition) throws Exception {
      if ( condition == 'xyz') {
         return C.getHelper();
      } else {
          return B.getHelper();
      }
  }
}

public class B extends A {
  protected static A b;

  @Override
  public A getHelper() {
    b = new B();
    return b;
  }

 @Override
  public void launchHandle() {
   System.out.println("Launching Handle");
  }

  public String getName() {
   return "I am from Class B";
  }
}

public class C extends A {
  protected static A c;

  @Override
  public A getHelper() {
    c = new C();
    return c;
  }

 @Override
  public void launchHandle() {
   System.out.println("Launching Handle from C");
  }

  public String getValue() {
   return "I am from Class C";
  }
}

**Executor class**

public class Executor {

  public static void main(String[] args) {
      A aa = a.initHelper(condition);
   }
}

Now in the above approach, i am unable to access methods like aa.getName() from Class B OR aa.getValue() from Class C, which makes sense. However how to get these methods in executor class? Executor does not know anything about Class B & C and should not know. Executor is only aware of Class A, but want to access methods SubClass methods from B & C which are extended from Class A.

Please help design this and what could be best way to solve this.

Thanks in advance.

Upvotes: 2

Views: 120

Answers (2)

Chetan Kinger
Chetan Kinger

Reputation: 15212

Executor is only aware of Class A, but want to access methods SubClass methods from B & C which are extended from Class A.

If you take a closer look at your code, you will notice that the only contract constant across all your classes is the launchHandle method (baring getHelper and initHelper which are simply used for instantiating the right subclass). There is no real relation between B and C other than the fact that their instantiation is controlled by A.

This is how I would consider approaching the problem :

Executor Factory

Make Executor an abstract class rather than making it the entry point of your program :

public abstract class Executor {
    public abstract void performTask();
    public static void execute(String condition) {
       Executor executor = null;
       if ( condition.equals("xyz")) {
          executor = new AExector();
       } else {
          executor = new BExecutor();
       }
       executor.performTask();
    }

}

Executor implementations

Create a different implementation for operating on B called BExecutor :

public class BExecutor extends Executor {

    public void performTask() {
      System.out.println("launching handle from B");
      //create or get data to perform the task on
      B b = new B();
      String name = b.getName();
      System.out.println("I am from "+name);

    }
}

Create a different implementation for operating on C called CExecutor :

public class CExecutor extends Executor {


    public void performTask() {
      System.out.println("launching handle from C");
       //create or get data to perform the task on
      C c = new C();
      String value = c.getValue();
      System.out.println("I am from "+value);

    }
}

Your main method can then look like this :

public static void main(String []args) { 
   Executor executor = Executor.execute(condition);
}

And for some reason, if you do find some common contract between B and C, you an always create an interface which both B and C can implement and use a reference of this interface instead of using a B or C reference.

Upvotes: 2

alexgbelov
alexgbelov

Reputation: 3121

Add getName and getValue to A as abstract methods.

Upvotes: 1

Related Questions