Существует множество определений того, что называется «Программирование для интерфейса, а не реализация». Попробуем понять этот принцип дизайна.

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

Интерфейсы - это просто контракты или подписи, и они ничего не знают о реализациях.

Так что давайте узнаем это на примере.

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

import com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl;

import java.util.Date;

public class Utils{

    public static XMLGregorianCalendarImpl getXmlGregorianCalendar(Date date) {

            // create a XMLGregorianCalendarImpl instance
            XMLGregorianCalendarImpl calendar= new XMLGregorianCalendarImpl();
            calendar.setYear(date.getYear());
            calendar.setMonth(date.getMonth());
            return calendar;
    }

}

В этом классе Utils getXmlGregorianCalendar () используется для получения календарного времени XMLGregorianCalendarImpl. Поскольку это служебный класс, его можно использовать в нескольких экземплярах.

import com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl;

import java.util.Date;

public class Usages {

    public static void main(String[] args) {

        Date date = new Date();
        //usage 1
        XMLGregorianCalendarImpl usage1 = Utils.getXmlGregorianCalendar(date);
        System.out.println(usage1.getYear());

        //usage 2
        XMLGregorianCalendarImpl usage2 = Utils.getXmlGregorianCalendar(date);
        System.out.println(usage2.getMonth());
    }
}

Этот код отлично работал в Java JDK 8, и нам нужно перенести код на JDK 10. Затем возникает эта проблема. Предыдущий XMLGregorianCalendarImpl не включен в новую версию, и ему пришлось использовать другую реализацию.

Поэтому нам нужно изменить метод getXmlGregorianCalendar () и все способы его использования.

Если он использовался многими экземплярами, нам нужно изменить все его использования и метод getXmlGregorianCalendar (). Необходимо было изменить не только тело метода, но и тип возвращаемого значения.

Очень неприятная задача. Не правда ли? мы могли бы преодолеть это, если будем следовать принципу проектирования «Программирование в интерфейс». Давайте правильно переделаем этот код.

Давайте посмотрим на класс XMLGregorianCalendarImpl. он является наследником абстрактного класса XMLGregorianCalendar.

Давайте изучим переработанный класс Utils.

import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class Utils{

    public static XMLGregorianCalendar getXmlGregorianCalendar(Date date) {

        XMLGregorianCalendar calendar = null;
        GregorianCalendar c = new GregorianCalendar();
        c.setTime(date);
        try {
            calendar = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return calendar;

    }
}

Здесь getXmlGregorianCalendar () возвращает абстрактный класс с именем XMLGregorianCalendar. он специально не возвращает реализацию.

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

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

Если вы хотите понять этот принцип на более простом примере, перейдите по этой ссылке.