Пусть часть библиотеки классов с помощью следующей иерархии:Эффективный способ разделить ту же реализацию интерфейса между двумя или более классов
class Super {
void doSomething() {
System.out.println("Super is doing something");
}
}
class SubOne extends Super {
@Override
void doSomething() {
System.out.println("SubOne is doing something");
}
void doSomethingElse() {
System.out.println("SubOne is doing something else");
}
}
class SubTwo extends Super {
@Override
void doSomething() {
System.out.println("SubTwo is doing something");
}
void doSomethingDifferent() {
System.out.println("SubTwo is doing something different");
}
}
Теперь кто-то определяет новое поведение предлагая интерфейс, который имеет отношение как к SubOne и классы SubTwo:
interface NewBehavior {
void doSomethingNew();
}
насколько я могу сказать, если мы не можем изменить исходный код для супер, SubOne и SubTwo, есть два способа определить новые версии SubOne и SubTwo, которые реализуют NewBehavior.
Один реализовать NewBehavior в подклассе супер, а затем создать новые версии SubOne и SubTwo наследования новой версии супер (и, возможно, обертывание SubOne и объектов SubTwo):
class ExtendingSuperNewBehavior extends Super
implements NewBehavior {
@Override
public void doSomethingNew() {
System.out.println("ExtendingSuperNewBehavior is doing something new");
}
}
class ExtendingSuperSubOneNewBehavior extends ExtendingSuperNewBehavior {
// Here we need to either wrap SubOne or redefine doSomethingElse()
// with the same implementation.
// SubOne mSubOne = new SubOne();
// void doSomethingElse() {
// mSubOne.doSomethingElse();
// }
void doSomethingElse() {
System.out.println("SubOne is doing something else");
}
}
class ExtendingSuperSubTwoNewBehavior extends ExtendingSuperNewBehavior {
// Here we need to either wrap SubTwo or redefine doSomethingDifferent()
// with the same implementation.
// SubTwo mSubTwo = new SubTwo();
// void doSomethingDifferent() {
// mSubTwo.doSomethingDifferent();
// }
void doSomethingDifferent() {
System.out.println("SubTwo is doing something different");
}
}
Другой определить класс, который реализует NewBehavior и завернуть экземпляр в каждой из новых версий SubOne и SubTwo:
class NewBehaviorImpl implements NewBehavior {
@Override
public void doSomethingNew() {
System.out.println("NewBehaviorImpl is doing something new");
}
}
class ImplementingSubOne extends SubOne
implements NewBehavior {
NewBehavior mNewBehavior = new NewBehaviorImpl();
public void doSomethingNew() {
mNewBehavior.doSomethingNew();
}
}
class ImplementingSubTwo extends SubTwo
implements NewBehavior {
NewBehavior mNewBehavior = new NewBehaviorImpl();
public void doSomethingNew() {
mNewBehavior.doSomethingNew();
}
}
Очевидно, что оба эти метода работают, но если SubOne и/или SubTwo подвергать большой интерфейс (как классы библиотеки обычно do) существует много способов пересылки метода независимо от того, какой метод выбран.
Может ли кто-нибудь подумать о способе повторного использования той же реализации интерфейса, которая позволила бы избежать пересылки кода? Это очень помогло бы.
Образец наблюдателя, использующий обратные вызовы, может стоить –