Apa artinya "memprogram ke antarmuka"?

814

Saya telah melihat ini disebutkan beberapa kali dan saya tidak jelas apa artinya. Kapan dan mengapa Anda melakukan ini?

Saya tahu apa yang dilakukan antarmuka, tetapi fakta saya tidak jelas tentang hal ini membuat saya berpikir saya kehilangan menggunakannya dengan benar.

Apakah itu hanya jika Anda melakukannya:

IInterface classRef = new ObjectWhatever()

Anda bisa menggunakan kelas apa saja yang mengimplementasikan IInterface? Kapan Anda perlu melakukan itu? Satu-satunya hal yang dapat saya pikirkan adalah jika Anda memiliki metode dan Anda tidak yakin objek apa yang akan dilewati kecuali untuk penerapannya IInterface. Saya tidak bisa memikirkan seberapa sering Anda perlu melakukan itu.

Juga, bagaimana Anda bisa menulis metode yang mengambil objek yang mengimplementasikan antarmuka? Apakah itu mungkin?

Damien
sumber
3
Jika Anda dapat mengingat dan program Anda harus optimal, tepat sebelum kompilasi Anda mungkin ingin menukar deklarasi Antarmuka untuk implementasi yang sebenarnya. Seperti menggunakan antarmuka menambah tingkat tipuan yang memberikan hit kinerja. Sebarkan kode Anda yang diprogram ke antarmuka ...
Ande Turner
18
@ Ande Turner: itu saran yang buruk. 1). "program Anda harus optimal" bukan alasan yang baik untuk mengganti antarmuka! Kemudian Anda mengatakan "Bagikan kode Anda yang diprogram ke antarmuka ..." jadi Anda menyarankan agar diberikan persyaratan (1) Anda kemudian merilis kode sub-optimal?!?
Mitch Wheat
74
Sebagian besar jawaban di sini kurang tepat. Itu tidak berarti atau bahkan menyiratkan "menggunakan kata kunci antarmuka" sama sekali. Antarmuka adalah spesifikasi cara menggunakan sesuatu - identik dengan kontrak (lihat itu). Terpisah dari itu adalah implementasinya, yaitu bagaimana kontrak itu dipenuhi. Program hanya menentang jaminan dari metode / jenis sehingga, ketika metode / jenis diubah dengan cara yang masih mematuhi kontrak, itu tidak melanggar kode yang menggunakannya.
jyoungdev
2
@ apollodude217 yang sebenarnya adalah jawaban terbaik di seluruh halaman. Setidaknya untuk pertanyaan dalam judul, karena setidaknya ada 3 pertanyaan yang sangat berbeda di sini ...
Andrew Spencer
4
Masalah mendasar dengan pertanyaan seperti ini adalah mengasumsikan bahwa "pemrograman ke antarmuka" berarti "membungkus semuanya dalam antarmuka abstrak", yang konyol jika Anda menganggap istilah ini mendahului konsep antarmuka abstrak gaya Java.
Jonathan Allen

Jawaban:

1634

Ada beberapa jawaban indah di sini untuk pertanyaan-pertanyaan ini yang masuk ke segala macam detail besar tentang antarmuka dan kode kopling longgar, inversi kontrol dan sebagainya. Ada beberapa diskusi yang cukup memabukkan, jadi saya ingin mengambil kesempatan untuk memecah hal-hal sedikit untuk memahami mengapa antarmuka berguna.

Ketika saya pertama kali mulai terkena antarmuka, saya juga bingung tentang relevansinya. Saya tidak mengerti mengapa Anda membutuhkannya. Jika kita menggunakan bahasa seperti Java atau C #, kita sudah memiliki warisan dan saya melihat antarmuka sebagai bentuk warisan yang lebih lemah dan berpikir, "mengapa repot-repot?" Dalam arti saya benar, Anda dapat menganggap antarmuka sebagai semacam bentuk warisan yang lemah, tetapi di luar itu saya akhirnya memahami penggunaannya sebagai konstruk bahasa dengan menganggapnya sebagai alat untuk mengklasifikasikan ciri-ciri umum atau perilaku yang ditunjukkan oleh berpotensi banyak kelas objek yang tidak terkait.

Misalnya - katakan Anda memiliki permainan SIM dan memiliki kelas berikut:

class HouseFly inherits Insect {
    void FlyAroundYourHead(){}
    void LandOnThings(){}
}

class Telemarketer inherits Person {
    void CallDuringDinner(){}
    void ContinueTalkingWhenYouSayNo(){}
}

Jelas, kedua benda ini tidak memiliki kesamaan dalam hal pewarisan langsung. Tapi, bisa dibilang keduanya sama-sama menyebalkan.

Katakanlah game kita perlu memiliki beberapa hal acak yang mengganggu pemain game ketika mereka makan malam. Ini bisa menjadi HouseFlyatau satu Telemarketeratau keduanya - tetapi bagaimana Anda mengizinkan keduanya dengan satu fungsi? Dan bagaimana Anda meminta setiap jenis objek yang berbeda untuk "melakukan hal yang mengganggu" dengan cara yang sama?

Kunci untuk menyadari adalah bahwa keduanya Telemarketerdan HouseFlyberbagi perilaku yang secara umum ditafsirkan secara longgar meskipun mereka tidak sama dalam hal pemodelan mereka. Jadi, mari kita buat antarmuka yang bisa diterapkan keduanya:

interface IPest {
    void BeAnnoying();
}

class HouseFly inherits Insect implements IPest {
    void FlyAroundYourHead(){}
    void LandOnThings(){}

    void BeAnnoying() {
        FlyAroundYourHead();
        LandOnThings();
    }
}

class Telemarketer inherits Person implements IPest {
    void CallDuringDinner(){}
    void ContinueTalkingWhenYouSayNo(){}

    void BeAnnoying() {
        CallDuringDinner();
        ContinueTalkingWhenYouSayNo();
    }
}

Kami sekarang memiliki dua kelas yang masing-masing dapat mengganggu dengan caranya sendiri. Dan mereka tidak perlu berasal dari kelas dasar yang sama dan berbagi karakteristik inheren yang sama - mereka hanya perlu memenuhi kontrak IPest- bahwa kontrak itu sederhana. Anda hanya perlu BeAnnoying. Dalam hal ini, kita dapat membuat model berikut:

class DiningRoom {

    DiningRoom(Person[] diningPeople, IPest[] pests) { ... }

    void ServeDinner() {
        when diningPeople are eating,

        foreach pest in pests
        pest.BeAnnoying();
    }
}

Di sini kami memiliki ruang makan yang menerima sejumlah pengunjung dan sejumlah hama - perhatikan penggunaan antarmuka. Ini berarti bahwa di dunia kecil kita, anggota pestsarray sebenarnya bisa menjadi Telemarketerobjek atau HouseFlyobjek.

The ServeDinnermetode ini disebut ketika makan malam disajikan dan orang-orang kami di ruang makan yang seharusnya untuk makan. Dalam permainan kecil kami, saat itulah hama kami melakukan tugasnya - masing-masing hama diperintahkan untuk mengganggu melalui IPestantarmuka. Dengan cara ini, kita dapat dengan mudah memiliki keduanya Telemarketersdan HouseFlysmenjengkelkan dalam caranya masing-masing - kita hanya peduli bahwa kita memiliki sesuatu pada DiningRoomobjek yang merupakan hama, kita tidak benar-benar peduli apa itu dan mereka tidak dapat memiliki apa pun dalam sama dengan lainnya.

Contoh pseudo-code yang sangat dibuat-buat ini (yang menyeret jauh lebih lama daripada yang saya perkirakan) hanya dimaksudkan untuk menggambarkan jenis hal yang akhirnya menyalakan lampu bagi saya dalam hal ketika kita mungkin menggunakan antarmuka. Saya mohon maaf sebelumnya atas kekonyolan dari contoh ini, tetapi saya harap itu membantu dalam pengertian Anda. Dan, yang pasti, jawaban yang diposkan lainnya yang Anda terima di sini benar-benar mencakup keseluruhan penggunaan antarmuka saat ini dalam pola desain dan metodologi pengembangan.

Peter Meyer
sumber
3
Hal lain yang perlu dipertimbangkan adalah bahwa dalam beberapa kasus mungkin berguna untuk memiliki antarmuka untuk hal-hal yang "mungkin" mengganggu, dan memiliki beragam objek yang diimplementasikan BeAnnoyingsebagai no-op; interface ini mungkin ada di tempat, atau di samping, antarmuka untuk hal-hal yang menjengkelkan (jika kedua interface ada, "hal-hal yang yang mengganggu" antarmuka harus mewarisi dari "hal-hal yang mungkin mengganggu" interface). Kerugian dari menggunakan antarmuka seperti itu adalah bahwa implementasi dapat terbebani dengan menerapkan sejumlah metode rintisan yang "menjengkelkan". Keuntungannya adalah ...
supercat
4
Metode ini tidak dimaksudkan untuk mewakili metode abstrak - implementasinya tidak relevan dengan pertanyaan yang berfokus pada antarmuka.
Peter Meyer
33
Perilaku enkapsulasi, seperti IPest dikenal sebagai pola strategi kalau-kalau ada orang yang tertarik untuk menindaklanjuti dengan lebih banyak materi tentang hal itu ...
nckbrz
9
Menariknya, Anda tidak menunjukkan bahwa karena objek dalam IPest[]referensi IPest, Anda dapat memanggil BeAnnoying()karena mereka memiliki metode itu, sementara Anda tidak dapat memanggil metode lain tanpa gips. Namun, setiap objek BeAnnoying()metode individu akan dipanggil.
D. Ben Knoble
4
Penjelasan yang sangat bagus ... Saya hanya perlu mengatakannya di sini: Saya tidak pernah mendengar tentang antarmuka sebagai semacam mekanisme pewarisan yang longgar, tetapi saya tahu bahwa pewarisan digunakan sebagai mekanisme yang buruk untuk mendefinisikan antarmuka (misalnya, dalam Python biasa Anda lakukan sepanjang waktu).
Carlos H Romano
283

Contoh spesifik yang biasa saya berikan kepada siswa adalah bahwa mereka harus menulis

List myList = new ArrayList(); // programming to the List interface

dari pada

ArrayList myList = new ArrayList(); // this is bad

Ini terlihat persis sama dalam program pendek, tetapi jika Anda terus menggunakan myList100 kali dalam program Anda, Anda dapat mulai melihat perbedaan. Deklarasi pertama memastikan bahwa Anda hanya memanggil metode myListyang ditentukan oleh Listantarmuka (jadi tidak ada ArrayListmetode khusus). Jika Anda telah memprogram ke antarmuka dengan cara ini, nanti Anda dapat memutuskan bahwa Anda benar-benar membutuhkannya

List myList = new TreeList();

dan Anda hanya perlu mengubah kode Anda di satu tempat itu. Anda sudah tahu bahwa sisa kode Anda tidak melakukan apa pun yang akan rusak dengan mengubah implementasi karena Anda memprogram ke antarmuka .

Manfaatnya bahkan lebih jelas (saya pikir) ketika Anda berbicara tentang parameter metode dan mengembalikan nilai. Ambil ini sebagai contoh:

public ArrayList doSomething(HashMap map);

Deklarasi metode itu mengikat Anda pada dua implementasi konkret ( ArrayListdan HashMap). Segera setelah metode itu dipanggil dari kode lain, setiap perubahan pada tipe itu mungkin berarti Anda harus mengubah kode panggilan juga. Akan lebih baik memprogram ke antarmuka.

public List doSomething(Map map);

Sekarang tidak masalah ListAnda kembali seperti apa, atau jenis apa Mapyang diteruskan sebagai parameter. Perubahan yang Anda buat di dalam doSomethingmetode tidak akan memaksa Anda untuk mengubah kode panggilan.

Bill the Lizard
sumber
Komentar bukan untuk diskusi panjang; percakapan ini telah dipindahkan ke obrolan .
Yvette
Penjelasannya sangat jelas. Sangat membantu
samuel luswata
Saya punya pertanyaan tentang alasan Anda menyebutkan "Deklarasi pertama memastikan bahwa Anda hanya memanggil metode pada myList yang ditentukan oleh antarmuka Daftar (jadi tidak ada metode spesifik ArrayList). Jika Anda telah memprogram ke antarmuka dengan cara ini, nanti Anda dapat memutuskan bahwa Anda benar-benar membutuhkan List myList = new TreeList (); dan Anda hanya perlu mengubah kode Anda di satu tempat itu. " Mungkin saya salah paham, saya bertanya-tanya mengapa Anda perlu mengubah ArrayList menjadi TreeList jika Anda ingin "memastikan bahwa Anda hanya memanggil metode di myList"?
user3014901
1
@ user3014901 Ada sejumlah alasan mengapa Anda mungkin ingin mengubah jenis daftar yang Anda gunakan. Seseorang mungkin memiliki kinerja pencarian yang lebih baik, misalnya. Intinya adalah bahwa jika Anda memprogram ke antarmuka Daftar, akan lebih mudah untuk mengubah kode Anda ke implementasi yang berbeda nanti.
Bill the Lizard
73

Pemrograman ke antarmuka mengatakan, "Saya membutuhkan fungsi ini dan saya tidak peduli dari mana asalnya."

Pertimbangkan (di Jawa), Listantarmuka versus ArrayListdan LinkedListkelas konkret. Jika yang saya pedulikan adalah bahwa saya memiliki struktur data yang berisi banyak item data yang harus saya akses melalui iterasi, saya akan memilih List(dan itu 99% dari waktu). Jika saya tahu bahwa saya perlu memasukkan / menghapus waktu-konstan dari kedua ujung daftar, saya mungkin memilih LinkedListimplementasi konkret (atau lebih mungkin, gunakan antarmuka Antrian ). Jika saya tahu saya perlu akses acak dengan indeks, saya akan memilih ArrayListkelas yang konkret.

kdgregory
sumber
1
sepenuhnya setuju yaitu kemerdekaan antara apa yang dilakukan vs bagaimana hal itu dilakukan. Dengan mempartisi sebuah sistem di sepanjang komponen independen, Anda berakhir dengan sistem yang sederhana dan dapat digunakan kembali (lihat Simple Made Easy oleh orang yang menciptakan Clojure)
beluchin
38

Menggunakan antarmuka adalah faktor utama dalam membuat kode Anda mudah diuji selain menghapus kopling yang tidak perlu antara kelas Anda. Dengan membuat antarmuka yang mendefinisikan operasi di kelas Anda, Anda memungkinkan kelas yang ingin menggunakan fungsionalitas itu kemampuan untuk menggunakannya tanpa tergantung pada kelas implementasi Anda secara langsung. Jika nanti Anda memutuskan untuk mengubah dan menggunakan implementasi yang berbeda, Anda hanya perlu mengubah bagian dari kode di mana implementasi tersebut dipakai. Sisa kode tidak perlu diubah karena tergantung pada antarmuka, bukan kelas pelaksana.

Ini sangat berguna dalam membuat unit test. Di kelas yang diuji Anda memilikinya tergantung pada antarmuka dan menyuntikkan contoh antarmuka ke kelas (atau pabrik yang memungkinkannya untuk membuat instance antarmuka sesuai kebutuhan) melalui konstruktor atau settor properti. Kelas menggunakan antarmuka yang disediakan (atau dibuat) dalam metodenya. Saat Anda menulis tes, Anda dapat mengejek atau memalsukan antarmuka dan menyediakan antarmuka yang merespons data yang dikonfigurasi dalam pengujian unit Anda. Anda dapat melakukan ini karena kelas Anda yang diuji hanya berurusan dengan antarmuka, bukan implementasi konkret Anda. Setiap kelas yang mengimplementasikan antarmuka, termasuk kelas tiruan atau palsu Anda, akan berlaku.

EDIT: Di bawah ini adalah tautan ke artikel di mana Erich Gamma membahas kutipannya, "Program ke antarmuka, bukan implementasi."

http://www.artima.com/lejava/articles/designprinciples.html

tvanfosson
sumber
3
Silakan, baca lagi wawancara ini: Gamma tentu saja berbicara tentang konsep antarmuka OO, bukan JAVA atau jenis kelas khusus C # (ISomething). Masalahnya adalah, kebanyakan orang meskipun dia berbicara tentang kata kunci, jadi kita sekarang memiliki banyak antarmuka yang tidak dibutuhkan (ada sesuatu).
Sylvain Rodrigue
Wawancara yang sangat bagus. Tolong, berhati-hatilah untuk pembaca masa depan, ada empat halaman dalam wawancara. Saya hampir menutup browser sebelum melihatnya.
Ad Infinitum
38

Pemrograman ke antarmuka sama sekali tidak ada hubungannya dengan antarmuka abstrak seperti yang kita lihat di Java atau .NET. Bahkan bukan konsep OOP.

Artinya adalah jangan main-main dengan internal objek atau struktur data. Gunakan Antarmuka Program Abstrak, atau API, untuk berinteraksi dengan data Anda. Di Jawa atau C # itu berarti menggunakan properti dan metode publik alih-alih akses bidang mentah. Untuk C itu berarti menggunakan fungsi bukan pointer mentah.

EDIT: Dan dengan database itu berarti menggunakan tampilan dan prosedur tersimpan daripada akses tabel langsung.

Jonathan Allen
sumber
5
Jawaban Terbaik. Gamma memberikan penjelasan serupa di sini: artima.com/lejava/articles/designprinciples.html (lihat halaman 2). Dia merujuk pada konsep OO tetapi Anda benar: itu lebih besar dari itu.
Sylvain Rodrigue
36

Anda harus melihat ke Inversion of Control:

Dalam skenario seperti itu, Anda tidak akan menulis ini:

IInterface classRef = new ObjectWhatever();

Anda akan menulis sesuatu seperti ini:

IInterface classRef = container.Resolve<IInterface>();

Ini akan masuk ke pengaturan berbasis aturan di container objek, dan membangun objek aktual untuk Anda, yang bisa menjadi ObjectWh Apapun. Yang penting adalah Anda bisa mengganti aturan ini dengan sesuatu yang menggunakan tipe objek lain secara bersamaan, dan kode Anda tetap berfungsi.

Jika kita meninggalkan IoC dari tabel, Anda dapat menulis kode yang mengetahui bahwa ia dapat berbicara ke objek yang melakukan sesuatu yang spesifik , tetapi tidak pada tipe objek yang mana atau bagaimana melakukannya.

Ini akan berguna ketika melewati parameter.

Adapun pertanyaan yang Anda tanda kurung "Juga, bagaimana Anda bisa menulis metode yang mengambil objek yang mengimplementasikan Antarmuka? Apakah itu mungkin?", Di C # Anda cukup menggunakan tipe antarmuka untuk tipe parameter, seperti ini:

public void DoSomethingToAnObject(IInterface whatever) { ... }

Ini terhubung tepat ke "bicara ke objek yang melakukan sesuatu yang spesifik." Metode yang didefinisikan di atas tahu apa yang diharapkan dari objek, bahwa ia mengimplementasikan segala sesuatu di IInterface, tetapi tidak peduli jenis objek apa itu, hanya bahwa ia mematuhi kontrak, yang merupakan antarmuka.

Misalnya, Anda mungkin terbiasa dengan kalkulator dan mungkin telah menggunakan beberapa di hari-hari Anda, tetapi sebagian besar waktu semuanya berbeda. Anda, di sisi lain, tahu bagaimana kalkulator standar harus bekerja, sehingga Anda dapat menggunakan semuanya, bahkan jika Anda tidak dapat menggunakan fitur spesifik yang dimiliki masing-masing kalkulator yang tidak dimiliki oleh yang lain.

Inilah keindahan antarmuka. Anda dapat menulis sepotong kode, yang tahu bahwa itu akan mendapatkan benda-benda yang diteruskan sehingga dapat mengharapkan perilaku tertentu. Tidak peduli seseorang berteriak-teriak objek apa itu, hanya saja itu mendukung perilaku yang diperlukan.

Biarkan saya memberi Anda sebuah contoh nyata.

Kami memiliki sistem terjemahan yang dibuat khusus untuk formulir windows. Sistem ini memutar melalui kontrol pada formulir dan menerjemahkan teks di masing-masing. Sistem tahu bagaimana menangani kontrol dasar, seperti tipe kontrol-yang-memiliki-teks-properti, dan hal-hal dasar serupa, tetapi untuk apa pun dasar, itu gagal.

Sekarang, karena kontrol mewarisi dari kelas yang telah ditentukan sebelumnya yang tidak dapat kita kendalikan, kita dapat melakukan salah satu dari tiga hal berikut:

  1. Bangun dukungan untuk sistem terjemahan kami untuk mendeteksi secara spesifik jenis kontrol yang digunakannya, dan menerjemahkan bit yang benar (mimpi buruk pemeliharaan)
  2. Bangun dukungan ke kelas dasar (tidak mungkin, karena semua kontrol mewarisi dari kelas yang telah ditentukan sebelumnya)
  3. Tambahkan dukungan antarmuka

Jadi kami melakukannya. 3. Semua kontrol kami menerapkan ILocalizable, yang merupakan antarmuka yang memberi kami satu metode, kemampuan menerjemahkan "dirinya" ke dalam wadah teks / aturan terjemahan. Dengan demikian, formulir tidak perlu mengetahui jenis kontrol yang telah ditemukannya, hanya saja ia mengimplementasikan antarmuka spesifik, dan tahu bahwa ada metode di mana ia dapat memanggil untuk melokalkan kontrol.

Lasse V. Karlsen
sumber
31
Mengapa menyebutkan IoC di awal karena ini hanya akan menambah lebih banyak kebingungan.
Kevin Le - Khnle
1
Setuju, saya akan mengatakan pemrograman terhadap antarmuka hanyalah teknik untuk membuat IoC lebih mudah dan dapat diandalkan.
terjetyl
28

Kode untuk Antarmuka Bukan Implementasi tidak ada hubungannya dengan Java, maupun konstruksinya Antarmuka.

Konsep ini dibawa ke menonjol dalam Pola / Geng Empat buku tetapi kemungkinan besar ada jauh sebelum itu. Konsepnya tentu ada jauh sebelum Jawa pernah ada.

Konstruk Java Interface dibuat untuk membantu ide ini (antara lain), dan orang-orang menjadi terlalu fokus pada konstruk sebagai pusat makna daripada maksud aslinya. Namun, itu adalah alasan kami memiliki metode dan atribut publik dan pribadi di Java, C ++, C #, dll.

Itu berarti hanya berinteraksi dengan objek atau antarmuka publik sistem. Jangan khawatir atau bahkan mengantisipasi bagaimana melakukan apa yang dilakukannya secara internal. Jangan khawatir tentang penerapannya. Dalam kode berorientasi objek, itu sebabnya kami memiliki metode / atribut publik vs. pribadi. Kami dimaksudkan untuk menggunakan metode publik karena metode pribadi hanya ada untuk digunakan secara internal, di dalam kelas. Mereka membuat implementasi kelas dan dapat diubah sesuai kebutuhan tanpa mengubah antarmuka publik. Asumsikan bahwa mengenai fungsionalitas, metode pada kelas akan melakukan operasi yang sama dengan hasil yang diharapkan setiap kali Anda menyebutnya dengan parameter yang sama. Hal ini memungkinkan penulis untuk mengubah cara kerja kelas, implementasinya, tanpa memutuskan bagaimana orang berinteraksi dengannya.

Dan Anda dapat memprogram ke antarmuka, bukan implementasi tanpa pernah menggunakan antarmuka Interface. Anda dapat memprogram ke antarmuka bukan implementasi di C ++, yang tidak memiliki konstruksi Antarmuka. Anda dapat mengintegrasikan dua sistem perusahaan besar jauh lebih kuat selama mereka berinteraksi melalui antarmuka publik (kontrak) daripada memanggil metode pada objek internal ke sistem. Antarmuka diharapkan untuk selalu bereaksi dengan cara yang diharapkan karena diberikan parameter input yang sama; jika diimplementasikan ke antarmuka dan bukan implementasi. Konsep ini bekerja di banyak tempat.

Goyang pikiran bahwa Java Interfaces ada hubungannya dengan konsep 'Program ke Antarmuka, Bukan Implementasi'. Mereka dapat membantu menerapkan konsep tersebut, tetapi mereka bukan konsepnya.

Bill Rosmus
sumber
1
Kalimat pertama mengatakan itu semua. Ini harus menjadi jawaban yang diterima.
madumlao
14

Sepertinya Anda mengerti bagaimana antarmuka bekerja tetapi tidak yakin kapan menggunakannya dan keuntungan apa yang mereka tawarkan. Berikut adalah beberapa contoh kapan antarmuka akan masuk akal:

// if I want to add search capabilities to my application and support multiple search
// engines such as Google, Yahoo, Live, etc.

interface ISearchProvider
{
    string Search(string keywords);
}

maka saya bisa membuat GoogleSearchProvider, YahooSearchProvider, LiveSearchProvider, dll.

// if I want to support multiple downloads using different protocols
// HTTP, HTTPS, FTP, FTPS, etc.
interface IUrlDownload
{
    void Download(string url)
}

// how about an image loader for different kinds of images JPG, GIF, PNG, etc.
interface IImageLoader
{
    Bitmap LoadImage(string filename)
}

lalu buat JpegImageLoader, GifImageLoader, PngImageLoader, dll.

Sebagian besar sistem add-in dan plugin bekerja di luar antarmuka.

Penggunaan populer lainnya adalah untuk pola Repositori. Katakanlah saya ingin memuat daftar kode pos dari berbagai sumber

interface IZipCodeRepository
{
    IList<ZipCode> GetZipCodes(string state);
}

maka saya bisa membuat XMLZipCodeRepository, SQLZipCodeRepository, CSVZipCodeRepository, dll. Untuk aplikasi web saya, saya sering membuat repositori XML sejak awal sehingga saya bisa mendapatkan sesuatu dan menjalankan sebelum Database SQL siap. Setelah database siap, saya menulis SQLRepository untuk menggantikan versi XML. Sisa kode saya tetap tidak berubah karena hanya berjalan dari antarmuka.

Metode dapat menerima antarmuka seperti:

PrintZipCodes(IZipCodeRepository zipCodeRepository, string state)
{
    foreach (ZipCode zipCode in zipCodeRepository.GetZipCodes(state))
    {
        Console.WriteLine(zipCode.ToString());
    }
}
Todd Smith
sumber
10

Itu membuat kode Anda jauh lebih mudah dikembangkan dan dapat dipertahankan ketika Anda memiliki set kelas yang sama. Saya seorang programmer junior, jadi saya bukan ahli, tetapi saya baru saja menyelesaikan sebuah proyek yang membutuhkan sesuatu yang serupa.

Saya bekerja pada perangkat lunak sisi klien yang berbicara ke server yang menjalankan perangkat medis. Kami sedang mengembangkan versi baru perangkat ini yang memiliki beberapa komponen baru yang kadang-kadang harus dikonfigurasikan oleh pelanggan. Ada dua jenis komponen baru, dan mereka berbeda, tetapi mereka juga sangat mirip. Pada dasarnya, saya harus membuat dua bentuk konfigurasi, dua daftar kelas, dua segalanya.

Saya memutuskan bahwa akan lebih baik untuk membuat kelas dasar abstrak untuk setiap jenis kontrol yang akan menampung hampir semua logika nyata, dan kemudian jenis turunan untuk mengurus perbedaan antara dua komponen. Namun, kelas dasar tidak akan dapat melakukan operasi pada komponen ini jika saya harus khawatir tentang tipe sepanjang waktu (well, mereka bisa saja melakukannya, tetapi akan ada pernyataan "jika" atau beralih di setiap metode) .

Saya mendefinisikan antarmuka sederhana untuk komponen-komponen ini dan semua kelas dasar berbicara dengan antarmuka ini. Sekarang ketika saya mengubah sesuatu, itu cukup 'hanya berfungsi' di mana-mana dan saya tidak memiliki duplikasi kode.

Ed S.
sumber
10

Banyak penjelasan di luar sana, tetapi untuk membuatnya lebih sederhana. Ambil contoh a List. Seseorang dapat mengimplementasikan daftar dengan sebagai:

  1. Array internal
  2. Daftar tertaut
  3. Implementasi lainnya

Dengan membuat antarmuka, ucapkan a List. Anda hanya kode untuk definisi Daftar atau apa Listartinya dalam kenyataan.

Anda dapat menggunakan jenis implementasi apa pun secara internal mengatakan suatu arrayimplementasi. Tapi misalkan Anda ingin mengubah implementasi karena alasan tertentu katakanlah bug atau kinerja. Maka Anda hanya perlu mengubah deklarasi List<String> ls = new ArrayList<String>()menjadi List<String> ls = new LinkedList<String>().

Di tempat lain dalam kode, Anda harus mengubah apa pun; Karena semuanya dibangun berdasarkan definisi List.

Jatin
sumber
8

Jika Anda memprogram di Java, JDBC adalah contoh yang bagus. JDBC mendefinisikan satu set antarmuka tetapi tidak mengatakan apa-apa tentang implementasi. Aplikasi Anda dapat ditulis terhadap set antarmuka ini. Secara teori, Anda memilih beberapa driver JDBC dan aplikasi Anda hanya akan berfungsi. Jika Anda menemukan ada driver JDBC lebih cepat atau "lebih baik" atau lebih murah atau untuk alasan apa pun, Anda dapat secara teori mengkonfigurasi ulang file properti Anda, dan tanpa harus membuat perubahan dalam aplikasi Anda, aplikasi Anda masih akan berfungsi.

Kevin Le - Khnle
sumber
Ini tidak hanya berguna jika driver yang lebih baik tersedia, itu memungkinkan untuk mengubah vendor database sepenuhnya.
Ken Liu
3
JDBC sangat buruk sehingga perlu diganti. Temukan contoh lain.
Joshua
JDBC buruk tetapi tidak karena alasan apa pun dengan antarmuka vs implementasi atau tingkat abstraksi. Jadi untuk menggambarkan konsep yang dimaksud, itu sempurna.
Erwin Smout
8

Pemrograman ke Antarmuka mengagumkan, mempromosikan kopling longgar. Seperti @lassevk sebutkan, Inversion of Control adalah penggunaan yang bagus untuk ini.

Selain itu, lihatlah ke kepala sekolah SOLID . di sini adalah seri video

Ia melewati hard coded (contoh sangat berpasangan) kemudian melihat antarmuka, akhirnya berkembang menjadi alat IoC / DI (NInject)

dbones
sumber
7

Saya terlambat datang ke pertanyaan ini, tetapi saya ingin menyebutkan di sini bahwa baris "Program ke antarmuka, bukan implementasi" memiliki beberapa diskusi yang baik dalam buku Pola Desain GoF (Gang of Four).

Disebutkan, pada hal. 18:

Program ke antarmuka, bukan implementasi

Jangan mendeklarasikan variabel sebagai instance dari kelas konkret tertentu. Sebaliknya, komit hanya ke antarmuka yang ditentukan oleh kelas abstrak. Anda akan menemukan ini sebagai tema umum dari pola desain dalam buku ini.

dan di atas itu, dimulai dengan:

Ada dua manfaat untuk memanipulasi objek hanya dalam hal antarmuka yang ditentukan oleh kelas abstrak:

  1. Klien tetap tidak mengetahui jenis objek tertentu yang mereka gunakan, selama objek tersebut mematuhi antarmuka yang diharapkan klien.
  2. Klien tetap tidak menyadari kelas yang mengimplementasikan objek ini. Klien hanya tahu tentang kelas abstrak yang mendefinisikan antarmuka.

Jadi dengan kata lain, jangan tuliskan kelas Anda sehingga memiliki quack()metode untuk bebek, dan kemudian bark()metode untuk anjing, karena mereka terlalu spesifik untuk implementasi kelas tertentu (atau subkelas). Alih-alih, tulis metode menggunakan nama yang cukup umum untuk digunakan di kelas dasar, seperti giveSound()atau move(), sehingga mereka dapat digunakan untuk bebek, anjing, atau bahkan mobil, dan kemudian klien dari kelas Anda dapat mengatakan .giveSound()daripada memikirkan apakah akan menggunakan quack()atau bark()atau bahkan menentukan jenisnya sebelum mengeluarkan pesan yang benar untuk dikirim ke objek.

nonopolaritas
sumber
6

Selain jawaban yang sudah dipilih (dan berbagai posting informatif di sini), saya akan sangat menyarankan untuk mengambil salinan Pola Desain Kepala Pertama . Ini adalah bacaan yang sangat mudah dan akan menjawab pertanyaan Anda secara langsung, menjelaskan mengapa itu penting, dan menunjukkan kepada Anda banyak pola pemrograman yang dapat Anda gunakan untuk memanfaatkan prinsip itu (dan lainnya).

ikan paus
sumber
5

Untuk menambah posting yang ada, kadang-kadang pengkodean ke antarmuka membantu proyek-proyek besar ketika pengembang bekerja pada komponen yang terpisah secara bersamaan. Yang Anda butuhkan hanyalah mendefinisikan antarmuka di muka dan menulis kode kepada mereka sementara pengembang lain menulis kode ke antarmuka yang Anda laksanakan.

e11s
sumber
4

Ini juga baik untuk Pengujian Unit, Anda dapat menyuntikkan kelas Anda sendiri (yang memenuhi persyaratan antarmuka) ke dalam kelas yang bergantung padanya

Richard
sumber
4

Dapat menguntungkan untuk memprogram ke antarmuka, bahkan ketika kita tidak bergantung pada abstraksi.

Pemrograman ke antarmuka memaksa kita untuk menggunakan subset objek yang sesuai secara kontekstual . Itu membantu karena:

  1. mencegah kita dari melakukan hal-hal yang tidak sesuai secara kontekstual, dan
  2. memungkinkan kami mengubah implementasi dengan aman di masa mendatang.

Misalnya, pertimbangkan Personkelas yang mengimplementasikan Frienddan Employeeantarmuka.

class Person implements AbstractEmployee, AbstractFriend {
}

Dalam konteks ulang tahun orang tersebut, kami memprogram ke Friendantarmuka, untuk mencegah memperlakukan orang tersebut seperti Employee.

function party() {
    const friend: Friend = new Person("Kathryn");
    friend.HaveFun();
}

Dalam konteks pekerjaan orang tersebut, kami memprogram ke Employeeantarmuka, untuk mencegah batas-batas tempat kerja yang kabur.

function workplace() {
    const employee: Employee = new Person("Kathryn");
    employee.DoWork();
}

Bagus. Kami telah berperilaku dengan tepat dalam konteks yang berbeda, dan perangkat lunak kami berfungsi dengan baik.

Jauh di masa depan, jika bisnis kita berubah untuk bekerja dengan anjing, kita dapat mengubah perangkat lunak dengan cukup mudah. Pertama, kita membuat Dogkelas yang mengimplementasikan keduanya Frienddan Employee. Lalu, kami beralih dengan aman new Person()ke new Dog(). Sekalipun kedua fungsi memiliki ribuan baris kode, pengeditan sederhana itu akan berfungsi karena kita tahu yang berikut ini benar:

  1. Fungsi partyhanya menggunakan Friendsubset dari Person.
  2. Fungsi workplacehanya menggunakan Employeesubset dari Person.
  3. Kelas Dogmengimplementasikan Frienddan Employeeantarmuka.

Di sisi lain, jika salah satu partyatau workplacediprogram terhadap Person, akan ada risiko keduanya memiliki Personkode-spesifik. Mengubah dari Personmenjadi Dogakan mengharuskan kita untuk menyisir kode untuk membasmi habis- Personspesifik kode yang Dogtidak mendukung.

Moral : pemrograman ke antarmuka membantu kode kita berperilaku dengan tepat dan siap untuk perubahan. Itu juga menyiapkan kode kita untuk bergantung pada abstraksi, yang membawa lebih banyak keuntungan.

Shaun Luttin
sumber
1
Dengan asumsi Anda tidak memiliki antarmuka yang terlalu luas, itu.
Casey
4

Jika saya menulis kelas baru Swimmeruntuk menambahkan fungsionalitas swim()dan perlu menggunakan objek kelas katakan Dog, dan Dogkelas ini mengimplementasikan antarmuka Animalyang menyatakan swim().

Di bagian atas hierarki ( Animal), sangat abstrak sedangkan di bagian bawah ( Dog) sangat konkret. Cara saya berpikir tentang "pemrograman untuk antarmuka" adalah bahwa, ketika saya menulis Swimmerkelas, saya ingin menulis kode saya terhadap antarmuka yang sejauh ini hierarki yang dalam hal ini adalah Animalobjek. Antarmuka bebas dari detail implementasi dan dengan demikian membuat kode Anda secara longgar digabungkan.

Detail implementasi dapat diubah dengan waktu, namun, itu tidak akan mempengaruhi kode yang tersisa karena semua yang Anda berinteraksi dengan antarmuka dan bukan implementasi. Anda tidak peduli seperti apa implementasinya ... yang Anda tahu adalah bahwa akan ada kelas yang akan mengimplementasikan antarmuka.

Abhishek Shrivastava
sumber
3

Jadi, hanya untuk mendapatkan ini dengan benar, keuntungan dari antarmuka adalah bahwa saya dapat memisahkan pemanggilan metode dari kelas tertentu. Alih-alih membuat instance antarmuka, di mana implementasinya diberikan dari kelas mana pun yang saya pilih yang mengimplementasikan antarmuka itu. Dengan demikian memungkinkan saya untuk memiliki banyak kelas, yang memiliki fungsionalitas yang serupa tetapi sedikit berbeda dan dalam beberapa kasus (kasus-kasus yang terkait dengan maksud antarmuka) tidak peduli objek mana itu.

Sebagai contoh, saya bisa memiliki antarmuka gerakan. Metode yang membuat sesuatu 'bergerak' dan objek apa pun (Orang, Mobil, Kucing) yang mengimplementasikan antarmuka gerakan dapat dilewati dan disuruh bergerak. Tanpa metode setiap mengetahui jenis kelas itu.

Damien
sumber
3

Bayangkan Anda memiliki produk yang disebut 'Zebra' yang dapat diperpanjang oleh plugin. Ia menemukan plugin dengan mencari DLL di beberapa direktori. Itu memuat semua DLL dan menggunakan refleksi untuk menemukan kelas yang menerapkanIZebraPlugin , dan kemudian memanggil metode antarmuka itu untuk berkomunikasi dengan plugin.

Ini membuatnya benar-benar independen dari kelas plugin tertentu - tidak peduli apa kelasnya. Itu hanya peduli bahwa mereka memenuhi spesifikasi antarmuka.

Antarmuka adalah cara untuk menentukan titik-titik ekstensibilitas seperti ini. Kode yang berbicara ke antarmuka lebih longgar digabungkan - pada kenyataannya tidak digabungkan sama sekali dengan kode spesifik lainnya. Itu dapat beroperasi dengan plugin yang ditulis bertahun-tahun kemudian oleh orang-orang yang belum pernah bertemu pengembang asli.

Anda bisa menggunakan kelas dasar dengan fungsi virtual - semua plugin akan diturunkan dari kelas dasar. Tetapi ini jauh lebih membatasi karena suatu kelas hanya dapat memiliki satu kelas dasar, sedangkan itu dapat mengimplementasikan sejumlah antarmuka.

Daniel Earwicker
sumber
3

Penjelasan C ++.

Pikirkan sebuah antarmuka sebagai metode umum kelas Anda.

Anda kemudian dapat membuat templat yang 'tergantung' pada metode publik ini untuk menjalankan fungsinya sendiri (ini membuat panggilan fungsi didefinisikan dalam antarmuka publik kelas). Katakanlah templat ini adalah wadah, seperti kelas Vektor, dan antarmuka yang digunakannya adalah algoritma pencarian.

Setiap kelas algoritme yang mendefinisikan fungsi / antarmuka yang dibuat oleh Vector akan memenuhi 'kontrak' (seperti yang dijelaskan seseorang dalam balasan asli). Algoritma bahkan tidak perlu dari kelas dasar yang sama; satu-satunya persyaratan adalah bahwa fungsi / metode yang bergantung pada Vector (antarmuka) didefinisikan dalam algoritma Anda.

Inti dari semua ini adalah bahwa Anda dapat menyediakan berbagai algoritma / kelas pencarian yang berbeda asalkan itu menyediakan antarmuka yang bergantung pada Vector (pencarian gelembung, pencarian sekuensial, pencarian cepat).

Anda mungkin juga ingin merancang wadah lain (daftar, antrian) yang akan memanfaatkan algoritma pencarian yang sama dengan Vector dengan meminta mereka memenuhi antarmuka / kontrak yang bergantung pada algoritma pencarian Anda.

Ini menghemat waktu (prinsip OOP 'code reuse') karena Anda dapat menulis algoritme satu kali, bukan lagi, lagi dan lagi, spesifik untuk setiap objek baru yang Anda buat tanpa terlalu memperumit masalah dengan pohon warisan yang tumbuh terlalu besar.

Adapun 'ketinggalan' tentang bagaimana hal-hal beroperasi; big-time (setidaknya dalam C ++), karena ini adalah bagaimana sebagian besar kerangka kerja Perpustakaan TEMPLATE Standar beroperasi.

Tentu saja ketika menggunakan kelas inheritance dan abstrak, metodologi pemrograman untuk suatu antarmuka berubah; tetapi prinsipnya sama, fungsi / metode publik Anda adalah antarmuka kelas Anda.

Ini adalah topik besar dan salah satu prinsip dasar Pola Desain.

Trae Barlow
sumber
3

Di Jawa, semua kelas konkret ini mengimplementasikan antarmuka CharSequence:

CharBuffer, String, StringBuffer, StringBuilder

Kelas-kelas konkret ini tidak memiliki kelas induk yang sama selain Object, jadi tidak ada yang menghubungkannya, selain fakta bahwa mereka masing-masing ada hubungannya dengan array karakter, mewakili, atau memanipulasi seperti itu. Misalnya, karakter String tidak dapat diubah setelah objek String dipakai, sedangkan karakter StringBuffer atau StringBuilder dapat diedit.

Namun masing-masing kelas ini mampu mengimplementasikan metode antarmuka CharSequence dengan tepat:

char charAt(int index)
int length()
CharSequence subSequence(int start, int end)
String toString()

Dalam beberapa kasus, kelas perpustakaan kelas Java yang dulu menerima String telah direvisi untuk sekarang menerima antarmuka CharSequence. Jadi, jika Anda memiliki instance dari StringBuilder, alih-alih mengekstraksi objek String (yang berarti instantiating instance objek baru), ia dapat hanya meneruskan StringBuilder itu sendiri ketika mengimplementasikan antarmuka CharSequence.

Antarmuka yang dapat ditambahkan yang diterapkan beberapa kelas memiliki banyak manfaat yang sama untuk situasi apa pun di mana karakter dapat ditambahkan ke instance instance objek kelas beton yang mendasarinya. Semua kelas konkret ini mengimplementasikan antarmuka yang dapat ditambahkan:

BufferedWriter, CharArrayWriter, CharBuffer, FileWriter, FilterWriter, LogStream, OutputStreamWriter, PipedWriter, PrintStream, PrintWriter, StringBuffer, StringBuilder, StringWriter, Writer

RogerV
sumber
Antarmuka terlalu buruk seperti CharSequencesangat anemia. Saya berharap Java dan .NET telah memungkinkan antarmuka untuk memiliki implementasi default, sehingga orang tidak akan pare down interface murni untuk tujuan meminimalkan kode boilerplate. Dengan adanya CharSequenceimplementasi yang sah, seseorang dapat meniru sebagian besar fungsi Stringdengan hanya menggunakan empat metode di atas, tetapi banyak implementasi dapat melakukan fungsi-fungsi itu jauh lebih efisien dengan cara lain. Sayangnya, bahkan jika implementasi tertentu CharSequencemenyimpan semuanya dalam satu char[]dan dapat melakukan banyak ...
supercat
... operasi seperti indexOfcepat, tidak mungkin penelepon yang tidak terbiasa dengan implementasi tertentu CharSequencedapat memintanya untuk melakukannya daripada harus digunakan charAtuntuk memeriksa setiap karakter individu.
supercat
3

Cerpen: Seorang tukang pos diminta pulang setelah pulang dan menerima sampul berisi (surat, dokumen, cek, kartu hadiah, lamaran, surat cinta) dengan alamat yang tertulis untuk dikirimkan.

Misalkan tidak ada penutup dan meminta tukang pos untuk pulang setelah rumah dan menerima semua barang dan mengirimkannya ke orang lain, tukang pos bisa bingung.

Jadi lebih baik bungkus dengan sampul (dalam cerita kami itu adalah antarmuka) maka dia akan melakukan tugasnya dengan baik.

Sekarang tugas tukang pos adalah untuk menerima dan mengirimkan sampul saja (dia tidak akan repot dengan apa yang ada di dalam sampul).

Buat jenis yang interfacebukan tipe aktual, tetapi implementasikan dengan tipe aktual.

Untuk membuat ke antarmuka berarti komponen Anda masuk ke dalam sisa kode dengan mudah

Saya memberi Anda sebuah contoh.

Anda memiliki antarmuka AirPlane seperti di bawah ini.

interface Airplane{
    parkPlane();
    servicePlane();
}

Misalkan Anda memiliki metode di kelas Controller Anda seperti Planes

parkPlane(Airplane plane)

dan

servicePlane(Airplane plane)

diimplementasikan dalam program Anda. Itu tidak akan BREAK kode Anda. Maksud saya, tidak perlu berubah selama menerima argumen sebagai AirPlane.

Karena akan menerima Airplane apapun meskipun jenis sebenarnya, flyer, highflyr, fighter, dll

Juga, dalam koleksi:

List<Airplane> plane; // Akan mengambil semua pesawatmu.

Contoh berikut akan menghapus pemahaman Anda.


Anda memiliki pesawat tempur yang mengimplementasikannya, jadi

public class Fighter implements Airplane {

    public void  parkPlane(){
        // Specific implementations for fighter plane to park
    }
    public void  servicePlane(){
        // Specific implementatoins for fighter plane to service.
    }
}

Hal yang sama untuk HighFlyer dan clasess lainnya:

public class HighFlyer implements Airplane {

    public void  parkPlane(){
        // Specific implementations for HighFlyer plane to park
    }

    public void  servicePlane(){
        // specific implementatoins for HighFlyer plane to service.
    }
}

Sekarang pikirkan kelas controller Anda menggunakan AirPlanebeberapa kali,

Misalkan kelas Controller Anda adalah ControlPlane seperti di bawah ini,

public Class ControlPlane{ 
 AirPlane plane;
 // so much method with AirPlane reference are used here...
}

Di sini keajaiban datang karena Anda dapat membuat AirPlaneinstance tipe baru Anda sebanyak yang Anda inginkan dan Anda tidak mengubah kode ControlPlanekelas.

Anda dapat menambahkan sebuah instance ...

JumboJetPlane // implementing AirPlane interface.
AirBus        // implementing AirPlane interface.

Anda juga dapat menghapus instance dari tipe yang dibuat sebelumnya.

Sanjay Rabari
sumber
2

Antarmuka seperti kontrak, di mana Anda ingin kelas implementasi Anda menerapkan metode yang tertulis dalam kontrak (antarmuka). Karena Java tidak menyediakan multiple inheritance, "pemrograman ke antarmuka" adalah cara yang baik untuk mencapai multiple inheritance.

Jika Anda memiliki kelas A yang sudah memperpanjang beberapa kelas B lain, tetapi Anda ingin kelas A juga mengikuti pedoman tertentu atau menerapkan kontrak tertentu, maka Anda dapat melakukannya dengan strategi "pemrograman untuk antarmuka".

Shivam Sugandhi
sumber
2

T: - ... "Bisakah Anda menggunakan kelas yang mengimplementasikan antarmuka?"
A: - Ya.

T: - ... "Kapan Anda perlu melakukan itu?"
A: - Setiap kali Anda membutuhkan kelas yang mengimplementasikan antarmuka.

Catatan: Kami tidak dapat membuat instance antarmuka yang tidak diimplementasikan oleh kelas - Benar.

  • Mengapa?
  • Karena antarmuka hanya memiliki prototipe metode, bukan definisi (hanya nama fungsi, bukan logika mereka)

AnIntf anInst = new Aclass();
// kita bisa melakukan ini hanya jika Aclass mengimplementasikan AnIntf.
// anInst akan memiliki referensi Aclass.


Catatan: Sekarang kita bisa mengerti apa yang terjadi jika Bclass dan Cclass menerapkan Dintf yang sama.

Dintf bInst = new Bclass();  
// now we could call all Dintf functions implemented (defined) in Bclass.

Dintf cInst = new Cclass();  
// now we could call all Dintf functions implemented (defined) in Cclass.

Apa yang kita miliki: Prototipe antarmuka yang sama (nama fungsi dalam antarmuka), dan sebut implementasi yang berbeda.

Daftar Pustaka: Prototipe - wikipedia

Meraj al Maksud
sumber
1

Program ke antarmuka memungkinkan untuk mengubah implementasi kontrak yang ditentukan oleh antarmuka dengan mulus. Ini memungkinkan sambungan longgar antara kontrak dan implementasi spesifik.

IInterface classRef = new ObjectWhatever()

Anda bisa menggunakan kelas apa saja yang mengimplementasikan IInterface? Kapan Anda perlu melakukan itu?

Lihatlah pertanyaan SE ini sebagai contoh yang bagus.

Mengapa antarmuka untuk kelas Java lebih disukai?

cara menggunakan kinerja hit Interface?

kalau begitu berapa?

Iya. Ini akan memiliki sedikit overhead kinerja dalam sub-detik. Tetapi jika aplikasi Anda memiliki persyaratan untuk mengubah implementasi antarmuka secara dinamis, jangan khawatir tentang dampak kinerja.

bagaimana Anda bisa menghindarinya tanpa harus mempertahankan dua bit kode?

Jangan mencoba untuk menghindari beberapa implementasi antarmuka jika aplikasi Anda membutuhkannya. Dengan tidak adanya kopling antarmuka yang ketat dengan satu implementasi spesifik, Anda mungkin harus menggunakan tambalan untuk mengubah satu implementasi ke implementasi lainnya.

Satu kasus penggunaan yang baik: Penerapan pola Strategi:

Contoh Dunia Nyata dari Pola Strategi

Ravindra babu
sumber
1

Program ke antarmuka adalah istilah dari buku GOF. saya tidak akan langsung mengatakan itu berkaitan dengan antarmuka java melainkan antarmuka nyata. untuk mencapai pemisahan lapisan bersih, Anda perlu membuat beberapa pemisahan antara sistem misalnya: Katakanlah Anda memiliki database konkret yang ingin Anda gunakan, Anda tidak akan pernah "memprogram ke basis data", sebaliknya Anda akan "memprogram ke antarmuka penyimpanan". Anda juga tidak akan pernah "memprogram ke Layanan Web" melainkan Anda akan memprogram ke "antarmuka klien". ini agar Anda dapat dengan mudah bertukar segalanya.

Saya menemukan aturan ini membantu saya:

1 . kami menggunakan antarmuka java ketika kami memiliki beberapa jenis objek. jika saya hanya memiliki satu objek, saya tidak mengerti intinya. jika setidaknya ada dua implementasi konkret dari beberapa ide, maka saya akan menggunakan antarmuka java.

2 . jika seperti yang saya nyatakan di atas, Anda ingin membawa decoupling dari sistem eksternal (sistem penyimpanan) ke sistem Anda sendiri (DB lokal) kemudian juga menggunakan antarmuka.

perhatikan bagaimana ada dua cara untuk mempertimbangkan kapan menggunakannya. semoga ini membantu.

j2emanue
sumber
0

Saya juga melihat banyak jawaban yang bagus dan jelas di sini, jadi saya ingin memberikan sudut pandang saya di sini, termasuk beberapa informasi tambahan apa yang saya perhatikan ketika menggunakan metode ini.

Pengujian unit

Selama dua tahun terakhir, saya telah menulis proyek hobi dan saya tidak menulis unit test untuknya. Setelah menulis sekitar 50 ribu baris, saya tahu akan perlu untuk menulis unit test. Saya tidak menggunakan antarmuka (atau sangat hemat) ... dan ketika saya melakukan tes unit pertama saya, saya menemukan itu rumit. Mengapa?

Karena saya harus membuat banyak instance kelas, digunakan untuk input sebagai variabel dan / atau parameter kelas. Jadi tes lebih mirip tes integrasi (harus membuat 'kerangka kerja' kelas yang lengkap karena semuanya terikat bersama).

Takut pada antarmuka Jadi saya memutuskan untuk menggunakan antarmuka. Ketakutan saya adalah bahwa saya harus mengimplementasikan semua fungsionalitas di mana-mana (di semua kelas yang digunakan) beberapa kali. Dalam beberapa hal ini benar, namun, dengan menggunakan warisan itu dapat dikurangi banyak.

Kombinasi antarmuka dan warisan saya menemukan kombinasi ini sangat bagus untuk digunakan. Saya memberikan contoh yang sangat sederhana.

public interface IPricable
{
    int Price { get; }
}

public interface ICar : IPricable

public abstract class Article
{
    public int Price { get { return ... } }
}

public class Car : Article, ICar
{
    // Price does not need to be defined here
}

Dengan cara ini menyalin kode tidak diperlukan, sementara masih memiliki manfaat menggunakan mobil sebagai antarmuka (ICar).

Michel Keijzers
sumber
0

Mari kita mulai dengan beberapa definisi pertama:

Antarmuka n.Himpunan semua tanda tangan yang didefinisikan oleh operasi objek disebut antarmuka ke objek

Ketik n.Antarmuka tertentu

Sebuah contoh sederhana dari antarmuka seperti yang didefinisikan di atas akan menjadi semua metode PDO objek seperti query(), commit(),close() dll, secara keseluruhan, tidak secara terpisah. Metode-metode ini, yaitu antarmuka yang mendefinisikan set lengkap pesan, permintaan yang dapat dikirim ke objek.

Sebuah tipe seperti didefinisikan di atas adalah antarmuka tertentu. Saya akan menggunakan antarmuka bentuk yang dibuat-buat untuk menunjukkan: draw(), getArea(),getPerimeter() dll ..

Jika suatu objek bertipe Basis Data, maksudnya ia menerima pesan / permintaan antarmuka basis data query(), commit()dll. Objek dapat terdiri dari banyak jenis. Anda dapat memiliki objek database dari jenis bentuk asalkan mengimplementasikan antarmuka, dalam hal ini akan menjadi sub-mengetik .

Banyak objek dapat memiliki banyak antarmuka / tipe yang berbeda dan mengimplementasikan antarmuka tersebut secara berbeda. Ini memungkinkan kita untuk mengganti objek, membiarkan kita memilih yang mana yang akan digunakan. Juga dikenal sebagai polimorfisme.

Klien hanya akan menyadari antarmuka dan bukan implementasinya.

Jadi dalam pemrograman intinya untuk sebuah antarmuka akan melibatkan membuat beberapa jenis kelas abstrak seperti Shapedengan antarmuka hanya ditentukan yaitu draw(), getCoordinates(), getArea()dll .. Dan kemudian memiliki kelas beton yang berbeda mengimplementasikan interface yang seperti kelas Circle, kelas Square, kelas Segitiga. Oleh karena itu program ke antarmuka bukan implementasi.

Robert Rocha
sumber
0

"Program untuk antarmuka" berarti tidak menyediakan kode keras dengan benar, artinya kode Anda harus diperpanjang tanpa merusak fungsi sebelumnya. Hanya ekstensi, bukan pengeditan kode sebelumnya.

ndoty
sumber