С помощью метода default
, который вы можете определить в интерфейсах, вы можете избежать наследования (extends
) и придерживаться реализации (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();
}
}
И используйте это, как вы делали ранее:
IWorker worker = new WorkerOne();
worker.doBetterWork();
Я хочу, чтобы все методы doWork () были заключены в одну и ту же операцию.
Лично мне не очень нравятся дизайны, в которых я раскрываю два метода в терминах API, в то время как клиенты этого класса должны вызывать только один из них. Это вводит в заблуждение.
Чтобы избежать этого, я бы, вероятно, использовал композицию и декоратор (не обычный декоратор, так как подпись отличается между двумя doWork()
методами).
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...
}
}
Теперь двусмысленность невозможна:
WorkWrapper worker = new WorkWrapper(new FooWork());
worker.doWork(); // just this method is exposed now in WorkWrapper
Вы можете объединить его с фабрикой, чтобы упростить задачу и скрыть детали реализации со стороны клиента:
WorkWrapper worker = FooWork.createWrapperFor();
worker.doWork();