2015-07-18 11 views
3

На работе я наткнулся на следующий дизайн в проекте Java:Странный дизайн интерфейса Java

Рассмотрим интерфейсы Foo, Bar и Baz следующим образом:

interface Bar { public int a(); }

interface Baz { public int b(); }

interface Foo extends Bar, Baz { public int c(); }

Нет ж, рассмотрим класс FooImpl:

public class FooImpl implements Foo { 

    private Bar bar; 
    private Baz baz; 

    public int a() { 
     return bar.a(); 
    } 
    public int b() { 
     return baz.b(); 
    } 
    public int c() { 
     return 0; 
    } 
} 

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

+1

Зависит от конкретной семантики для интерфейсов и авторов тех. В основном Foo основывается на Bar и Baz (код, который работает на баре или базе, также будет работать на Foo). FooImpl реализует один такой Foo. Если этот дизайн имеет смысл, это зависит от фактического использования Bar и Baz и Foo для потребителей этих интерфейсов. – eckes

ответ

4

Это позволяет такие вещи, как это:

Foo foo = new FooImpl(); 
useBar(foo); 

public void useBar(Bar bar) { 
    bar.a(); 
} 

ли это полезно, зависит от реального контекста. Ваш примерный код с классами и методами с бессмысленными именами не поддерживает рациональное суждение.

Другая вещь, которую следует отметить, - это ваш FooImpl, фактически реализованный как некая оболочка для Bar и Baz экземпляров. Это не (строго говоря) проблема с дизайном интерфейса.

+0

Спасибо за ответ! Я понимаю случай расширения от нескольких интерфейсов, но мой вопрос должен быть направлен скорее на реализацию класса.Мне кажется, что он вводит много псевдонимов методов, а также нарушает способность IDE создавать значимую иерархию вызовов (создавая бесконечный цикл). – nosman

+1

Ни одна из этих вещей не особенно плоха из (абстрагированного) дизайна. (Проблема IDE на самом деле указывает на кратковременный дизайн IDE, а не на код, который вы смотрите ...) Как я уже сказал в своем ответе, вам нужно взглянуть на эти вещи в контексте фактического использования, дело. Вам нужно рассмотреть, что он делает, почему он это делает, и каковы альтернативы. –

0

Чтобы сделать это действительно просто перенаправлять fooimpl с помощью своих СВОЙСТВ (в бар и БАЗ) «» метод и «б» метод

1

Я думаю, что это временное решение для множественного наследования (что не разрешено в Java). Вы не показывая реализаций для Bar и Baz, но давайте предположим, что они существуют:

public class BarImpl implements Bar { 

    @Override 
    public int a() { 
     return 1; 
    } 
} 

public class BazImpl implements Baz { 

    @Override 
    public int b() { 
     return 2; 
    } 
} 

Вы ни говорили нам, как Bar и Baz атрибуты экземпляра и установите FooImpl, потому что, если выполняется, как указано в вашем вопросе , вы получите NullPointerException как в FooImpl.a(), так и в FooImpl.b(). Опять же, давайте представим, как это может быть достигнуто:

public class FooImpl implements Foo { 

    private Bar bar; // better if final 

    private Baz baz; // better if final 

    // Constructor to properly initialize bar and baz 
    public FooImpl(Bar bar, Baz baz) { 
     this.bar = bar; 
     this.baz = baz; 
    } 

    @Override 
    public int a() { 
     return bar.a(); 
    } 

    @Override 
    public int b() { 
     return baz.b(); 
    } 

    @Override 
    public int c() { 
     return 0; 
    } 
} 

Электропроводка все вверх:

Bar bar = new BarImpl(); 
Baz baz = new BazImpl(); 

Foo foo = new FooImpl(bar, baz); 

int one = foo.bar(); // 1 
int two = foo.baz(); // 2 

В некотором смысле, FooImpl является «унаследовать» от обоих BarImpl и BazImpl, хотя это достигается с помощью делегация.

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