Hai! Hari ini kita akan menyentuh topik baharu yang penting: corak reka bentuk . Apakah corak-corak ini? Saya rasa anda mesti tahu ungkapan " jangan cipta semula roda ". Dalam pengaturcaraan, seperti dalam banyak kawasan lain, terdapat sejumlah besar situasi biasa. Memandangkan pembangunan perisian telah berkembang, penyelesaian siap sedia yang berfungsi telah dicipta untuk setiap satu daripadanya. Penyelesaian ini dipanggil corak reka bentuk. Mengikut konvensyen, corak ialah beberapa penyelesaian yang dirumuskan seperti ini: "jika anda perlu melakukan X dalam program anda, maka ini adalah cara terbaik untuk melakukannya". Terdapat banyak corak. Buku yang sangat baik "Kepala Corak Reka Bentuk Pertama", yang anda pasti akan biasa dengannya, didedikasikan untuk mereka.
Secara ringkasnya, corak terdiri daripada masalah biasa dan penyelesaian sepadan yang boleh dianggap sebagai sejenis piawai. Dalam pelajaran hari ini, kita akan menemui salah satu daripada corak ini: Penyesuai. Namanya menyatakan semuanya, dan anda telah menemui penyesuai berkali-kali dalam kehidupan sebenar. Beberapa penyesuai yang paling biasa ialah pembaca kad yang dimiliki oleh banyak komputer dan komputer riba.
Katakan kita mempunyai sejenis kad memori. Jadi apa masalahnya? Ia tidak tahu bagaimana untuk berinteraksi dengan komputer. Mereka tidak berkongsi antara muka biasa. Komputer mempunyai port USB, tetapi kami tidak boleh memasukkan kad memori di dalamnya. Kad tidak boleh dipalamkan ke dalam komputer, jadi kami tidak dapat menyimpan foto, video dan data kami yang lain. Pembaca kad ialah penyesuai yang menyelesaikan masalah ini. Lagipun, ia mempunyai kabel USB! Tidak seperti kad itu sendiri, pembaca kad boleh dipasang ke dalam komputer. Mereka berkongsi antara muka biasa dengan komputer: USB. Mari lihat bagaimana ini kelihatan dalam amalan:
Satu set kaedah adalah tepat apa itu antara muka. Seperti yang anda lihat, kelas ini mempunyai a
Walau bagaimanapun, antara muka
Dan walaupun


public interface USB {
void connectWithUsbCable();
}
Ini ialah antara muka USB kami dengan hanya satu kaedah untuk menyambung 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 kad memori. Ia sudah mempunyai 2 kaedah yang kami perlukan, tetapi inilah masalahnya: Ia tidak melaksanakan antara muka USB. Kad tidak boleh dimasukkan ke dalam 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 penyesuai kami! Apa yangCardReader
kelas lakukan dan apa sebenarnya yang menjadikannya penyesuai? Semuanya mudah. Kelas yang disesuaikan (MemoryCard) menjadi salah satu medan penyesuai. Ini masuk akal. Apabila kita meletakkan kad memori di dalam pembaca kad dalam kehidupan sebenar, ia juga menjadi sebahagian daripadanya. Tidak seperti kad memori, penyesuai berkongsi antara muka dengan komputer. Ia mempunyai kabel USB, iaitu ia boleh disambungkan ke peranti lain melalui USB. Itulah sebabnya kelas CardReader kami melaksanakan antara muka USB. Tetapi apa sebenarnya yang berlaku dalam kaedah ini? Tepat apa yang kita perlu berlaku! Penyesuai mewakilkan kerja ke kad memori kami. Sesungguhnya, penyesuai tidak melakukan apa-apa sendiri. Pembaca kad tidak mempunyai sebarang fungsi bebas. Tugasnya hanya untuk menyambungkan komputer dan kad memori untuk membolehkan kad melakukan kerjanya — menyalin fail!connectWithUsbCable()
kaedah) untuk memenuhi "keperluan" kad memori. Mari buat beberapa program klien yang akan meniru seseorang yang ingin menyalin data daripada kad memori:
public class Main {
public static void main(String[] args) {
USB cardReader = new CardReader(new MemoryCard());
cardReader.connectWithUsbCable();
}
}
Jadi apa yang kita dapat? Output konsol:
Memory card successfully inserted!
The data has been copied to the computer!
Cemerlang. Kami mencapai objektif kami! Berikut ialah pautan ke video dengan maklumat tentang corak Penyesuai:
Kelas abstrak Pembaca dan Penulis
Sekarang kita akan kembali ke aktiviti kegemaran kita: belajar tentang beberapa kelas baharu untuk bekerja dengan input dan output :) Saya tertanya-tanya berapa banyak yang telah kita pelajari. Hari ini kita akan bercakap tentangReader
dan Writer
kelas. Mengapa khusus kelas tersebut? Kerana ia berkaitan dengan bahagian kami sebelumnya tentang penyesuai. Mari kita periksa mereka dengan lebih terperinci. Kita akan mulakan dengan Reader
. Reader
ialah kelas abstrak, jadi kami tidak akan dapat mencipta objek secara eksplisit. Tetapi anda sebenarnya sudah biasa dengannya! Lagipun, anda sudah biasa dengan kelas BufferedReader
dan InputStreamReader
, yang merupakan keturunannya :)
public class BufferedReader extends Reader {
…
}
public class InputStreamReader extends Reader {
…
}
Kelas ini InputStreamReader
ialah penyesuai klasik. Seperti yang anda mungkin ingat, kita boleh menghantar InputStream
objek kepada pembinanya. Untuk melakukan ini, kami biasanya menggunakan pembolehubah System.in
:
public static void main(String[] args) {
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
}
Tetapi apa yang InputStreamReader
dilakukan? Seperti setiap penyesuai, ia menukar satu antara muka kepada yang lain. Dalam kes ini, InputStream
antara muka ke Reader
antara muka. Pada mulanya, kami mempunyai InputStream
kelas. Ia berfungsi dengan baik, tetapi anda hanya boleh menggunakannya untuk membaca bait individu. Di samping itu, kami mempunyai Reader
kelas abstrak. Ia mempunyai beberapa fungsi yang sangat berguna — ia tahu cara membaca aksara! Kita pasti memerlukan keupayaan ini. Tetapi di sini kita menghadapi masalah klasik yang biasanya diselesaikan oleh penyesuai — antara muka yang tidak serasi. Apakah maksudnya? Mari kita lihat dokumentasi Oracle. Berikut adalah kaedah kelas InputStream
. 
read()
kaedah (sebenarnya beberapa varian), tetapi ia hanya boleh membaca bait: sama ada bait individu, atau beberapa bait menggunakan penimbal. Tetapi pilihan ini tidak sesuai dengan kami — kami mahu membaca aksara. Kami memerlukan kefungsian yang telah dilaksanakan dalam Reader
kelas abstrak . Kita juga boleh melihat ini dalam dokumentasi. 
InputStream
dan Reader
tidak serasi! Seperti yang anda lihat, setiap pelaksanaan kaedah read()
mempunyai parameter dan nilai pulangan yang berbeza. Dan di sinilah kita perlukan InputStreamReader
! Ia akan bertindak sebagai penyesuai antara kelas kami. Seperti dalam contoh dengan pembaca kad, yang kami pertimbangkan di atas, kami meletakkan contoh kelas yang disesuaikan "di dalam" kelas penyesuai, iaitu kami menyerahkan satu kepada pembinanya. Dalam contoh sebelumnya, kami meletakkan MemoryCard
objek di dalam CardReader
. Sekarang kita menghantar InputStream
objek kepada InputStreamReader
pembina! Kami menggunakan System.in
pembolehubah biasa kami sebagai InputStream
:
public static void main(String[] args) {
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
}
Dan sememangnya, melihat dokumentasi untuk InputStreamReader
, kita dapat melihat bahawa penyesuaian berjaya :) Kini kita mempunyai kaedah untuk membaca aksara yang kita gunakan. 
System.in
objek kami (strim yang terikat pada papan kekunci) pada mulanya tidak membenarkan ini, pencipta bahasa menyelesaikan masalah ini dengan melaksanakan corak penyesuai. Kelas Reader
abstrak, seperti kebanyakan kelas I/O, mempunyai saudara kembar — Writer
. Ia mempunyai kelebihan besar yang sama seperti Reader
— ia menyediakan antara muka yang mudah untuk bekerja dengan aksara. Dengan aliran keluaran, masalah dan penyelesaiannya kelihatan sama seperti aliran input. Terdapat OutputStream
kelas yang hanya boleh menulis bait, terdapat aWriter
kelas abstrak yang tahu cara bekerja dengan aksara, dan terdapat dua antara muka yang tidak serasi. Masalah ini sekali lagi diselesaikan oleh corak penyesuai. Kami menggunakan OutputStreamWriter
kelas untuk menyesuaikan kedua-dua antara muka Writer
dan OutputStream
kelas dengan mudah antara satu sama lain. Selepas menghantar OutputStream
aliran bait kepada pembina, kita boleh menggunakan a OutputStreamWriter
untuk menulis aksara dan bukannya bait!
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 watak dengan kod 32144 (綐) pada fail kami, menghapuskan keperluan untuk berfungsi dengan bait :) Itu sahaja untuk hari ini. Jumpa anda dalam pelajaran seterusnya! :)
GO TO FULL VERSION