Parent wrapping child class method

itamar :

I have these Worker classes doing some job:

class WorkerOne implements IWorker {
    @Override
    public doWork(Resource resource){
     // do some work
    }
}

I want all doWork() methods to be wrapped by the same operation.

One way to achieve it is creating an abstract class as the following example:

abstract class WorkWrapper implements IWorker {
    @Override
    public doBetterWork(){
       Resource resource = // ...
       doWork(resource)
       resource .close();
    }
}


class WorkerOne extends WorkWrapper {

    protected doWork(Resource resource){
     // do some work
    }
}

and invoke the Worker as:

WorkerOne worker = new WorkerOne();
worker.doBetterWork();

For some reasons I prefer not to use inheritance. Is there a better solution to do this wrapping?

davidxxx :

With default method that you can defined in interfaces you could avoid inheritance (extends) and stick to implement (implements) :

class WorkerOne implements IWorker {
    @Override
    public void doWork(Resource resource){
     // do some work
    }
}

public interface IWorker {
    void doWork(Resource resource);

    default void doBetterWork(){
       Resource resource = // ...
       doWork(resource)
       reource.close();
    }
}

And use it like you previously did :

IWorker worker = new WorkerOne();
worker.doBetterWork(); 

I want all doWork() methods to be wrapped by the same operation.

Personally I don't like very much designs where I expose two methods in terms of API while only one of them should be invoked by clients of the class. That is misleading.
To avoid it, I would probably use composition and decorator (not the conventional decorator as the signature differs between the two doWork() methods).

public interface IWorker {
    void doWork(Resource resource);
}

class WorkWrapper{

    private IWorker decorated;
    public WorkWrapper(IWorker decorated){
       this.decorated = decorated;
    }
    @Override
    public doWork(){
       Resource resource = // ...
       decorated.doWork(resource);
       reource.close();
    }
}

class FooWork implements IWorker {

    @Override
    public doWork(Resource resource){
          // do something...
    } 
 }

Now no ambiguities is possible :

WorkWrapper worker = new WorkWrapper(new FooWork());
worker.doWork(); // just this method is exposed now in WorkWrapper 

You can combine it to the factory to make things simpler and hiding implementation details from client side:

WorkWrapper worker = FooWork.createWrapperFor();
worker.doWork(); 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=122585&siteId=1