"Program do interfejsu". Co to znaczy? [duplikat]

Możliwy duplikat:
Co to znaczy "programować do interfejsu"?

Ciągle natykam się na ten termin:

Program do interfejsu.

Co to dokładnie znaczy? Scenariusz prawdziwego projektu byłby bardzo doceniany.
Author: Community, 2010-01-02

8 answers

Mówiąc prościej, zamiast pisać swoje zajęcia w sposób, który mówi

I depend on this specific class to do my work

Piszesz to w sposób, który mówi

Polegam na jakiejkolwiek klasie, która wykonuje te rzeczy, aby wykonać moją pracę.

Pierwszy przykład reprezentuje klasę, która zależy od konkretnej implementacji do wykonania swojej pracy. Z natury nie jest to zbyt elastyczne.

Drugi przykład reprezentuje klasę zapisaną do interfejsu . Nie obchodzi go, jakiego konkretnego obiektu używasz, po prostu dba o to, że implementuje określone zachowanie. To sprawia, że klasa jest znacznie bardziej elastyczna, ponieważ może być wyposażona w dowolną liczbę konkretnych implementacji do swojej pracy.

Jako przykład, dana klasa może wymagać wykonania logowania. Jeśli zapisujesz klasę do depend on a TextFileLogger, klasa jest na zawsze zmuszona do zapisywania swoich rekordów dziennika do pliku tekstowego. Jeśli chcesz Zmień zachowanie logowania, musisz zmienić samą klasę. Klasa jest ściśle powiązana ze swoim loggerem.

Jeśli jednak napiszesz klasę, aby była zależna od interfejsu Iloggera, a następnie dostarczysz klasie TextFileLogger, osiągniesz to samo, ale z dodatkową korzyścią bycia znacznie bardziej elastycznym. Jesteś w stanie dostarczyć dowolny inny rodzaj Iloggera do woli, bez zmiany samej klasy. Klasa i jej logger są teraz luźno połączone, a Twój klasa jest znacznie bardziej elastyczna.

 71
Author: Eric King,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-02 19:11:54

Interfejs jest zbiorem powiązanych metod, które zawierają tylko sygnatury tych metod-a nie rzeczywistą implementację.
Jeśli klasa implementuje interfejs (class Car implements IDrivable), musi dostarczyć kod dla wszystkich sygnatur zdefiniowanych w interfejsie.

Przykład podstawowy:
Musisz klasy samochodu i roweru. Oba implementują interfejs IDrivable:

interface IDrivable 
{
    void accelerate();
    void brake();      
}

class Car implements IDrivable 
{
   void accelerate()
   { System.out.println("Vroom"); }

   void brake()
   { System.out.println("Queeeeek");}
}

class Bike implements IDrivable 
{
   void accelerate()
   { System.out.println("Rattle, Rattle, ..."); }

   void brake()
   { System.out.println("..."); }
}

Teraz Załóżmy, że masz zbiór obiektów, które są wszystkie "drivable" (ich klasy implementują IDrivable):

List<IDrivable> vehicleList = new ArrayList<IDrivable>();
list.add(new Car());
list.add(new Car());
list.add(new Bike());
list.add(new Car());
list.add(new Bike());
list.add(new Bike());

Jeśli chcesz teraz zapętlić tę kolekcję, możesz polegać na tym, że każdy obiekt w tej kolekcji implementuje accelerate():

for(IDrivable vehicle: vehicleList) 
{
  vehicle.accelerate(); //this could be a bike or a car, or anything that implements IDrivable
}

Wywołując tę metodę interfejsu, nie programujesz do implementacji, ale do interfejsu - kontraktu, który zapewnia, że obiekt wywołania implementuje określoną funkcjonalność.
To samo zachowanie można osiągnąć za pomocą dziedziczenia, ale wywodzącego się ze wspólnej klasy bazowej skutkuje ciasnym połączeniem, którego można uniknąć za pomocą interfejsów.

 18
Author: Thomas Zoechling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-02 19:21:13

Polimorfizm zależy od programowania interfejsu, a nie implementacji.

Są dwie korzyści z manipulowania obiektami wyłącznie pod względem interfejsu zdefiniowanego przez klasy abstrakcyjne:

  1. klienci pozostają nieświadomi specyficznych typów obiektów, których używają, o ile obiekty przylegają do interfejsu, którego oczekują klienci.
  2. klienci pozostają nieświadomi klas implementujących te obiekty. Klienci wiedzą tylko o klasie abstrakcyjnej(klasach) definiującej interfejs.

To tak znacznie zmniejsza zależności implementacji między podsystemami, że prowadzi do tej zasady programowania do interfejsu.

Zobacz wzór metody Fabrycznej {[14] } dla dalszego rozumowania tego projektu.

[[0]} źródło: " wzorce projektowe: elementy oprogramowania Obiektowego wielokrotnego użytku" by G. O. F.

Zobacz Też: Wzór Fabryczny. Kiedy stosować metody fabryczne?

 8
Author: Joe Phillips,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:46:41

Prawdziwe przykłady są applenty. Jeden z nich:

Dla JDBC, używasz interfejsu java.sql.Connection. Jednak każdy sterownik JDBC dostarcza własną implementację Connection. Nie musisz nic wiedzieć o konkretnej implementacji, ponieważ jest zgodna z interfejsem Connection.

Kolejny pochodzi z java collections framework. Istnieje interfejs java.util.Collection, który definiuje size, add i remove metody (m.in. Możesz więc używać wszystkich typów Kolekcje zamiennie . Załóżmy, że masz:

public float calculateCoefficient(Collection collection) {
    return collection.size() * something / somethingElse;
}

I dwie inne metody, które odwołują się do tej. Jedna z innych metod używa LinkedList, ponieważ jest bardziej efektywna dla swoich celów, a druga używa TreeSet.

Ponieważ zarówno LinkedList, jak i TreeSet implementują interfejs Collection, można użyć tylko jednej metody do obliczenia współczynnika. Nie ma potrzeby powielania kodu.

I tu pojawia się" program do interfejsu " - nie dbaj o to, jak dokładnie zaimplementowana jest metoda size(), wiesz, że powinna zwracać rozmiar kolekcji - tzn. masz zaprogramowany interfejs Collection, a nie w szczególności LinkedList i TreeSet.

Ale radzę znaleźć lekturę-być może książkę ( na przykład" Thinking in Java") - w której pojęcie jest szczegółowo wyjaśnione.

 7
Author: Bozho,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-02 18:53:49

Każdy obiekt ma odsłonięty interfejs. Kolekcja posiada Add, Remove, At, itd. Gniazdo może mieć Send, Receive, Close i tak dalej.

Każdy obiekt, do którego można uzyskać odniesienie, ma konkretną implementację tych interfejsów.

Obie te rzeczy są oczywiste, jednak to, co jest nieco mniej oczywiste...

Twój kod nie powinien polegać na szczegółach implementacji obiektu, tylko na jego opublikowanym interfejsie.

Jeśli weźmiesz go do ekstremum, kodowałbyś tylko przeciwko Collection<T> i tak dalej (zamiast ArrayList<T>). Bardziej praktycznie, po prostu upewnij się, że możesz zamienić się czymś identycznym koncepcyjnie bez łamania kodu.

Aby uzyskać przykład Collection<T>: masz zbiór czegoś, używasz ArrayList<T>, ponieważ dlaczego nie . Powinieneś się upewnić, że Twój Kod się nie zepsuje, jeśli, powiedzmy, w przyszłości użyjesz LinkedList<T>.

 4
Author: Kevin Montrose,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-02 18:42:49

Zasadniczo oznacza to, że jedyną częścią biblioteki, na której będziesz korzystać, jest jej API (Application programming interface) i że nie powinieneś opierać swojej aplikacji na konkretnej implementacji biblioteki.

Np. Przypuszczalnie masz bibliotekę, która daje Ci stack. Zajęcia dają Ci kilka metod. Powiedzmy push, pop, isempty i top. Powinieneś napisać swoją aplikację opierając się tylko na nich. Jednym ze sposobów na naruszenie tego byłoby Podglądanie wewnątrz i dowiedzieć się, że stos jest zaimplementowany przy użyciu tablicy pewnego rodzaju tak, że jeśli pop z pustego stosu, można dostać jakiś rodzaj wyjątku indeks i następnie złapać to zamiast polegać na metodzie isempty, które zapewnia Klasa. Pierwsze podejście zawiedzie, jeśli dostawca biblioteki przełączy się z użycia tablicy na użycie jakiejś listy, podczas gdy ta druga nadal będzie działać, zakładając, że jego API nadal będzie działać.

 2
Author: Noufal Ibrahim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-02 18:43:35

"Programowanie do interfejsu" dzieje się, gdy używasz bibliotek, innego kodu, od którego zależy twój własny kod. Następnie, sposób, w jaki inny kod przedstawia się Tobie, nazwy metod, ich parametry, wartości zwrotne itp. składają się na interfejs , do którego musisz zaprogramować. Więc chodzi o to, jak używasz kodu innych firm.

Oznacza to również, że nie musisz dbać o wewnętrzne elementy kodu, od których zależą, dopóki interfejs pozostaje taki sam, Twój kod jest bezpieczny (cóż, bardziej lub mniej...)

Technicznie istnieją drobniejsze szczegóły, jak na przykład pojęcia językowe zwane "interfejsami" w Javie.

Jeśli chcesz dowiedzieć się więcej, możesz zapytać, co oznacza "implementacja interfejsu"...

 2
Author: raoulsson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-02 18:46:24

Myślę, że to jedna z mantr Ericha Gamma. Nie mogę znaleźć, Kiedy pierwszy raz to opisał( przed książką GOF), ale można to zobaczyć w wywiadzie na: http://www.artima.com/lejava/articles/designprinciples.html

 1
Author: Uri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-02 18:39:33