Причина использования интерфейса, чем реализовать его позже

Мой вопрос заключается в том, чтобы просто: почему люди делают это:

Интерфейс:

public interface CarDAO {

void addCar(Car car);

List<Car> readAll();

void deleteCar(Long id);

}

чем создать класс, который реализует carDAO

    public class CarDAOImpl implements CarDAO {

    private SessionFactory sessionFactory;

    private Session getCurrentSession(){

    return sessionFactory.getCurrentSession();

    }

    public void addCar(Car car) {

all the code to add the car    
    }
    public void deleteCar(Car car) {

all the code to delete the car    
    }

почему бы просто не создать carCRUDclass без интерфейса?

5 ответов

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

Клиенты имеют дело с интерфейсом; им не нужно знать, как что-то делается.

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

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

Посмотрите на пакет java.sql - это все интерфейсы. Поставщики драйверов JDBC предоставляют реализации, поэтому вам не нужно беспокоиться о поставщиках. Если вы меняете базы данных, вы просто помещаете новый JAR в ваш CLASSPATH. Весь ваш код, который имеет дело с интерфейсами, все еще работает.

Еще один замечательный пример - API коллекций java.util. Вы должны предпочесть интерфейс java.util.List. Будь то ArrayList или LinkedList за этим не будет иметь значения для ваших клиентов.

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

Термин "контракт" используется в связи с интерфейсами. Интерфейс определяет "контракт" между приложением и реализацией.

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

Допустим, у вас есть ArrayList и у вас есть несколько классов, которые реализуют CarDAO. Этими классами могут быть Car1, Car2 и Car3. Поскольку все они реализуют класс CarDAO, все они могут быть добавлены в ранее объявленный ArrayList. Также вы можете перебирать все реализации CarDAO и вызывать общие методы, так как все они наследуют методы CarDAO.

Потому что может быть более одной реализации CarDAO, Один будет выбран во время компиляции или во время выполнения.

Другая причина - абстрагировать вызывающих абонентов от знания, какая реализация используется. Может быть реализация JPA сегодня, может быть реализация MongoDB завтра. Клиенты не должны менять.

Интерфейсы определяют поведение, а объекты, которые реализуют интерфейсы, обеспечивают конкретную реализацию объекта для каждого поведения.
В вашем примере CarDAO - это интерфейс, и, скажем, у него есть два разработчика
1. HibernateCarDAO
2. MybatisCarDAO

Теперь каждая из этих реализаций будет обеспечивать функциональность addCar(Car c) и deleteCar(), позволяя пользователю CarDAO выбрать соответствующую реализацию.

Я бы посоветовал взглянуть на некоторые посты, в которых говорится об соглашениях по именованию для реализаций Такие имена, как CarDAOImpl, действительно сбивают с толку эту концепцию. Более чистые имена сделают концепцию выдающейся.

Другие вопросы по тегам