Выберите наследование или интерфейс для реализации шаблона проектирования в Java? - PullRequest
2 голосов
/ 09 июня 2010

Я просто хочу внедрить некоторые шаблоны проектирования в мой Java-код, но я не знаю, какой стиль использовать - предпочтительнее наследование или интерфейс?А почему?

Ответы [ 4 ]

9 голосов
/ 09 июня 2010

Шаблоны проектирования - это не просто случайная вставка в ваше приложение. Это вещи во время разработки, а не сыр пармезан, который вы добавляете в свой код после того, как он уже испечен.

Тем не менее, семя Джоша Блоха Эффективная Java настоятельно рекомендует разработчикам использовать интерфейсы для общего поведения, а не наследования. Это соответствует моему собственному опыту.

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

5 голосов
/ 09 июня 2010

Шаблоны проектирования не «внедряются» в ваш код - сначала вы должны заметить, что ваша проблема похожа на проблему, решаемую многими другими, и что они создали шаблон, который решает проблему. Самые известные из них здесь

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

2 голосов
/ 09 июня 2010

Две функции не являются взаимоисключающими. Интерфейс и реализации определяют типы и совместимость с типом. Наследование позволяет эффективно делиться кодом. В классическом дизайне иерархия типов выражается с помощью интерфейсов, а повторное использование кода достигается с помощью наследования.

1 голос
/ 14 июня 2010

Я согласен, что не следует думать о введении ИЛИ, используя некоторые шаблоны проектирования. Шаблоны проектирования предназначены для решения очень специфических проблем в данном контексте.

Об интерфейсах и наследовании:

Интерфейсы используются, когда вам нужен полиморфизм времени выполнения. Итак, вы определяете интерфейс и можете иметь несколько различных его реализаций. В коде клиента вы можете просто объявить ссылку как тип интерфейса. Теперь вы не беспокоитесь о фактическом типе объекта, переданного клиенту во время выполнения. Вы просто заботитесь о вызове метода по ссылке.

 interface Car {
        void startEngine();

        void stopEngine();
    }

    class Maruti implements Car {

        public void startEngine() {
            System.out.println("Maruti engine started");
        }

        @Override
        public void stopEngine() {
            System.out.println("Maruti engine stopped");
        }
    }

    class Porsche implements Car {

        @Override
        public void startEngine() {
            System.out.println("Porsche engine started");
        }

        @Override
        public void stopEngine() {
            System.out.println("Porsche engine stopped");
        }
    }

В приведенном выше примере в качестве клиента вы бы просто объявили ссылку как Тип автомобиля. И во время выполнения вы можете иметь объект Maruti или объект Porsche, вам все равно. То, что вас волнует, это просто позвонить startEngine или stopEngine.

Наследование обычно используется для повторного использования и расширения кода. Итак, у вас есть общий код в двух классах, и оба кажутся принадлежащими к общему типу, тогда вы можете создать родительский класс (иногда абстрактный) и переместить общий код в родительский класс. Таким образом, вы можете избавиться от дубликата кода. Другой вариант использования - это расширяемость, иногда у вас нет контроля над исходным кодом класса, и все же вы хотели бы добавить / изменить некоторое поведение. Вы можете использовать наследование и переопределить определенные методы.

Существует еще одна вещь, называемая "состав" , которая является предпочтительным способом наследования для расширяемости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...