0

I'm not very good at CS domain language, so I hope I can make myself understood.

I'm looking for a DRY way to create objects of on of two types based on a boolean flag. Both types have one method each - differently named - which implements the same logic. This logic I'd like to implement only once (think of an abstract super class here, which won't work in this case though, I think).

Example

To be more concrete, consider this. There are two classes (in my case one inheriting from org.eclipse.core.runtime.jobs.Job and one inheriting org.eclipse.ui.progress.UIJob (which itself extends org.eclipse.core.runtime.jobs.Job)).

Both implement a certain logic (the same!) in a run-type method. For the class extending Job, this method is called run(IProgressMonitor m), for the one extending UIJob this method is called runInUIThread(IProgressMonitor m).

I want to be able to

  1. Implement the logic only once (DRY!), and for example have both run() and runInUIThread simply call something like super.run(). But because in Java classes cannot extend more than one class, I cannot do something like MyUIJob extends UIJob, MyAbstractJob where MyAbstractJob implements abstractRun(), and MyUIJob#runInUIThread(){ super.abstractRun() }.
  2. Start either job (MyJob and MyUIJob) from the same method (say, in a handler class), depending on, for example, a flag boolean isUIJob.

I've had a brief look at design patterns such as "AbstractFactory" and "Prototype", but these don't seem to work for my case as either would still need "double extension inheritance". (Or am I wrong?)

Hence the question: How can I implement the above in Java?

s.d
  • 4,017
  • 5
  • 35
  • 65

1 Answers1

1

regarding point #1: instead of inheritence, you can use delegation:

public class MyJob extends Job {
  private JobLogic logic;
  public MyJob(JobLogic logic) {
    this.logic = logic;
  }
  IStatus run(IProgressMonitor monitor) {
    return logic.run(monitor);
  }
}

public class MyUIJob extends UIJob {
  private JobLogic logic;
  public MyUIJob(JobLogic logic) {
    this.logic = logic;
  }
  IStatus runInUIThread(IProgressMonitor monitor) {
    return logic.run(monitor);
  }
}

public class JobLogic {
  IStatus run(IProgressMonitor monitor) {
    // logic goes here ...
  }
}

by the way, you could use a dependency injection framework to bind the Jobs to different logic instances, if required.

Sharon Ben Asher
  • 13,849
  • 5
  • 33
  • 47
  • @plalx, according to [this](http://stackoverflow.com/questions/1224830/difference-between-strategy-pattern-and-delegation-pattern), there is a difference between Strategy pattern and delegation principle. the Strategy pattern actually includes different concrete implementations of same interface, while the question here is how to maintain the DRY concept were one concrete implementation is specified once – Sharon Ben Asher Nov 26 '15 at 13:54
  • Ok yeah, I guess you are right... however, does the unit test mock implementation counts as a different strategy? ;) That's probably not something you would mock anyway, but I'm just playing devil's advocate here hehe. – plalx Nov 26 '15 at 13:58