2015-06-16 1 views
2

Пусть часть библиотеки классов с помощью следующей иерархии:Эффективный способ разделить ту же реализацию интерфейса между двумя или более классов

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) существует много способов пересылки метода независимо от того, какой метод выбран.

Может ли кто-нибудь подумать о способе повторного использования той же реализации интерфейса, которая позволила бы избежать пересылки кода? Это очень помогло бы.

+0

Образец наблюдателя, использующий обратные вызовы, может стоить –

ответ

0

Рассмотрите возможность использования библиотеки AOP (Aspect Oriented Programming), такой как AspectJ. Одна из вещей, которые вы можете сделать с AOP, представляет дополнительные атрибуты или методы для существующих классов. В вашем примере вы должны добавить новый метод прозрачно в подклассы SubOne и SubTwo, не затрагивая эти классы. Приложение AOP в основном будет использовать прокси-серверы для ваших первоначальных классов прозрачным способом.

Смежные вопросы