Hai! Hari ini kita akan menyentuh topik baru yang penting: pola desain . Apa pola-pola ini? Saya pikir Anda harus tahu ungkapan " jangan menemukan kembali roda ". Dalam pemrograman, seperti di banyak bidang lain, ada banyak situasi umum. Seiring berkembangnya pengembangan perangkat lunak, solusi siap pakai yang berfungsi telah dibuat untuk masing-masingnya. Solusi ini disebut pola desain. Secara konvensi, sebuah pola adalah beberapa solusi yang dirumuskan seperti ini: "jika Anda perlu melakukan X dalam program Anda, maka ini adalah cara terbaik untuk melakukannya". Ada banyak pola. Buku luar biasa "Head First Design Patterns", yang pasti sudah Anda kenal, didedikasikan untuk mereka. Ringkasnya, sebuah pola terdiri dari masalah umum dan solusi yang sesuai yang dapat dianggap sebagai semacam standar. Dalam pelajaran hari ini, kita akan bertemu dengan salah satu pola berikut: Adaptor. Namanya mengatakan itu semua, dan Anda telah menemukan adaptor berkali-kali dalam kehidupan nyata. Beberapa adaptor yang paling umum adalah pembaca kartu yang dimiliki banyak komputer dan laptop. Misalkan kita memiliki semacam kartu memori. Jadi apa masalahnya? Ia tidak tahu bagaimana berinteraksi dengan komputer. Mereka tidak berbagi antarmuka yang sama. Komputer memiliki port USB, tetapi kami tidak dapat memasukkan kartu memori ke dalamnya. Kartu tersebut tidak dapat dicolokkan ke komputer, jadi kami tidak dapat menyimpan foto, video, dan data lainnya. Pembaca kartu adalah adaptor yang memecahkan masalah ini. Lagi pula, ia memiliki kabel USB! Berbeda dengan kartu itu sendiri, pembaca kartu dapat dicolokkan ke komputer. Mereka berbagi antarmuka yang sama dengan komputer: USB. Mari kita lihat bagaimana tampilannya dalam praktik:
public interface USB {
void connectWithUsbCable();
}
Ini adalah antarmuka USB kami dengan hanya satu metode untuk menghubungkan melalui USB.
public class MemoryCard {
public void insert() {
System.out.println("Memory card successfully inserted!");
}
public void copyData() {
System.out.println("The data has been copied to the computer!");
}
}
Ini adalah kelas kami yang mewakili kartu memori. Itu sudah memiliki 2 metode yang kita butuhkan, tapi inilah masalahnya: Itu tidak mengimplementasikan antarmuka USB. Kartu tidak dapat dimasukkan ke port USB.
public class CardReader implements USB {
private MemoryCard memoryCard;
public CardReader(MemoryCard memoryCard) {
this.memoryCard = memoryCard;
}
@Override
public void connectWithUsbCable() {
this.memoryCard.insert();
this.memoryCard.copyData();
}
}
Dan inilah adaptor kami! ApaCardReader
kelas lakukan dan apa sebenarnya yang membuatnya menjadi adaptor? Semuanya sederhana. Kelas yang diadaptasi (MemoryCard) menjadi salah satu bidang adaptor. Ini masuk akal. Saat kita meletakkan kartu memori di dalam pembaca kartu di kehidupan nyata, itu juga menjadi bagian darinya. Berbeda dengan kartu memori, adaptor berbagi antarmuka dengan komputer. Ini memiliki kabel USB, yaitu dapat dihubungkan ke perangkat lain melalui USB. Itu sebabnya kelas CardReader kami mengimplementasikan antarmuka USB. Tapi apa sebenarnya yang terjadi di dalam metode ini? Persis apa yang kita butuhkan terjadi! Adaptor mendelegasikan pekerjaan ke kartu memori kami. Memang, adaptor itu sendiri tidak melakukan apa-apa. Pembaca kartu tidak memiliki fungsi independen. Tugasnya hanya menghubungkan komputer dan kartu memori agar kartu dapat melakukan tugasnya — menyalin file!connectWithUsbCable()
method) untuk memenuhi "kebutuhan" kartu memori. Mari buat beberapa program klien yang akan mensimulasikan seseorang yang ingin menyalin data dari kartu memori:
public class Main {
public static void main(String[] args) {
USB cardReader = new CardReader(new MemoryCard());
cardReader.connectWithUsbCable();
}
}
Jadi apa yang kita dapatkan? Keluaran konsol:
Memory card successfully inserted!
The data has been copied to the computer!
Bagus sekali. Kami mencapai tujuan kami! Berikut tautan ke video dengan informasi tentang pola Adaptor:
Kelas abstrak Reader dan Writer
Sekarang kita akan kembali ke aktivitas favorit kita: belajar tentang beberapa kelas baru untuk bekerja dengan masukan dan keluaran :) Saya ingin tahu berapa banyak yang telah kita pelajari. Hari ini kita akan berbicara tentangReader
dan Writer
kelas. Mengapa khusus kelas-kelas itu? Karena mereka terkait dengan bagian kami sebelumnya tentang adaptor. Mari kita periksa lebih detail. Kita akan mulai dengan Reader
. Reader
adalah kelas abstrak, jadi kita tidak akan bisa membuat objek secara eksplisit. Tapi Anda sebenarnya sudah terbiasa dengan itu! Lagi pula, Anda sangat mengenal kelas BufferedReader
dan InputStreamReader
, yang merupakan keturunannya :)
public class BufferedReader extends Reader {
…
}
public class InputStreamReader extends Reader {
…
}
Kelas InputStreamReader
adalah adaptor klasik. Seperti yang mungkin Anda ingat, kita dapat meneruskan InputStream
objek ke konstruktornya. Untuk melakukan ini, kami biasanya menggunakan System.in
variabel:
public static void main(String[] args) {
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
}
Tapi apa InputStreamReader
fungsinya? Seperti setiap adaptor, ini mengubah satu antarmuka ke antarmuka lainnya. Dalam hal ini, InputStream
antarmuka ke Reader
antarmuka. Awalnya, kami memiliki InputStream
kelas. Ini berfungsi dengan baik, tetapi Anda hanya dapat menggunakannya untuk membaca byte individual. Selain itu, kami memiliki Reader
kelas abstrak. Ini memiliki beberapa fungsi yang sangat berguna — ia tahu cara membaca karakter! Kita tentu membutuhkan kemampuan ini. Namun di sini kita menghadapi masalah klasik yang biasanya diselesaikan dengan adaptor — antarmuka yang tidak kompatibel. Maksudnya itu apa? Mari kita lihat dokumentasi Oracle. Berikut adalah metode kelas InputStream
. Seperangkat metode persis seperti antarmuka. Seperti yang Anda lihat, kelas ini memilikiread()
metode (sebenarnya beberapa varian), tetapi hanya dapat membaca byte: baik byte individu, atau beberapa byte menggunakan buffer. Tetapi opsi ini tidak cocok untuk kami — kami ingin membaca karakter. Kami membutuhkan fungsionalitas yang sudah diimplementasikan di Reader
kelas abstrak . Kita juga bisa melihat ini di dokumentasi. Namun, antarmuka InputStream
dan Reader
tidak kompatibel! Seperti yang Anda lihat, setiap implementasi metode read()
memiliki parameter dan nilai pengembalian yang berbeda. Dan di sinilah kita membutuhkan InputStreamReader
! Ini akan bertindak sebagai adaptor antara kelas kami. Seperti pada contoh dengan pembaca kartu, yang kami pertimbangkan di atas, kami menempatkan turunan dari kelas yang diadaptasi "di dalam" kelas adaptor, yaitu kami meneruskan satu ke konstruktornya. Pada contoh sebelumnya, kita meletakkan MemoryCard
objek di dalam CardReader
. Sekarang kita meneruskan InputStream
objek ke InputStreamReader
konstruktor! Kami menggunakan variabel yang kami kenal System.in
sebagai InputStream
:
public static void main(String[] args) {
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
}
Dan memang, melihat dokumentasi untuk InputStreamReader
, kita dapat melihat bahwa adaptasinya berhasil :) Sekarang kita memiliki metode untuk membaca karakter yang kita miliki. Dan meskipun System.in
objek kami (aliran yang terikat ke keyboard) pada awalnya tidak mengizinkan ini, pembuat bahasa memecahkan masalah ini dengan menerapkan pola adaptor. Kelas Reader
abstrak, seperti kebanyakan kelas I/O, memiliki saudara kembar — Writer
. Ini memiliki keuntungan besar yang sama seperti Reader
— menyediakan antarmuka yang nyaman untuk bekerja dengan karakter. Dengan aliran keluaran, masalah dan solusinya terlihat sama dengan aliran masukan. Ada OutputStream
kelas yang hanya bisa menulis byte, ada aWriter
kelas abstrak yang tahu cara bekerja dengan karakter, dan ada dua antarmuka yang tidak kompatibel. Masalah ini sekali lagi diselesaikan dengan pola adaptor. Kami menggunakan OutputStreamWriter
kelas untuk dengan mudah mengadaptasi dua antarmuka kelas Writer
dan OutputStream
satu sama lain. Setelah meneruskan OutputStream
aliran byte ke konstruktor, kita dapat menggunakan an OutputStreamWriter
untuk menulis karakter daripada byte!
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
OutputStreamWriter streamWriter = new OutputStreamWriter(new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt"));
streamWriter.write(32144);
streamWriter.close();
}
}
Kami menulis karakter dengan kode 32144 (綐) ke file kami, menghilangkan kebutuhan untuk bekerja dengan byte :) Itu saja untuk hari ini. Sampai jumpa di pelajaran selanjutnya! :)
GO TO FULL VERSION