JavaRush /Java Blogu /Random-AZ /Dizayn nümunəsi adapteri

Dizayn nümunəsi adapteri

Qrupda dərc edilmişdir
Salam! Bu gün biz vacib bir yeni mövzuya toxunacağıq - naxışlar və ya başqa sözlə - dizayn nümunələri . Nümunələr nədir? Düşünürəm ki, siz "təkəri yenidən kəşf etməyin" ifadəsini bilirsiniz. Proqramlaşdırmada, bir çox başqa sahələrdə olduğu kimi, çoxlu sayda tipik vəziyyətlər mövcuddur. Onların hər biri üçün proqramlaşdırmanın inkişafı prosesində hazır işçi həllər yaradılmışdır. Bunlar dizayn nümunələridir. Nisbətən desək, nümunə bir vəziyyətə həll təklif edən müəyyən bir nümunədir: "proqramınızın bir şey etməsi lazımdırsa, bunu ən yaxşı şəkildə necə etmək olar". Çoxlu naxışlar var, onlara "Dizayn Nümunələrini Öyrənmək" əla kitabı həsr olunub, mütləq oxumalısınız. Dizayn nümunəsi "Adapter" - 2Mümkün qədər qısa desək, nümunə ümumi problemdən və onun həllindən ibarətdir ki, bu da artıq bir növ standart sayıla bilər. Bugünkü mühazirəmizdə biz “Adapter” adlanan bu nümunələrdən biri ilə tanış olacağıq. Onun adı çox gözəldir və siz real həyatda adapterlərlə bir dəfədən çox rastlaşmısınız. Ən çox yayılmış adapterlərdən biri bir çox kompüter və noutbukla təchiz edilmiş kart oxuyucularıdır. Adapter dizayn nümunəsi - 3Təsəvvür edin ki, bir növ yaddaş kartımız var. Problem nədir? Fakt budur ki, o, kompüterlə necə əlaqə quracağını bilmir. Onların ümumi interfeysi yoxdur. Kompüterdə USB konnektoru var, lakin siz ona yaddaş kartını daxil edə bilməzsiniz. Kartı kompüterə daxil etmək mümkün deyil, buna görə fotoşəkillərimizi, videolarımızı və digər məlumatları saxlaya bilməyəcəyik. Kart oxuyucusu bu problemi həll edən adapterdir. Axı onun USB kabeli var! Kartın özündən fərqli olaraq, kart oxuyucusu kompüterə daxil edilə bilər. Onların kompüterlə ümumi interfeysi var - USB. Bir nümunə ilə bunun necə görünəcəyini görək:
public interface USB {

   void connectWithUsbCable();
}
Bu, USB kabelimizi daxil etmək üçün yeganə üsul olan USB interfeysimizdir:
public class MemoryCard {

   public void insert() {
       System.out.println("Карта памяти успешно вставлена!");
   }

   public void copyData() {
       System.out.println("Данные скопированы на компьютер!");
   }
}
Bu, yaddaş xəritəsini həyata keçirən sinifimizdir. Artıq bizə lazım olan 2 üsul var, amma problem buradadır: USB interfeysini tətbiq etmir. Kartı USB yuvasına daxil etmək mümkün deyil.
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();
   }
}
Və burada adapterimiz var! SinifCardReader nə edir və niyə adapterdir? Bu sadədir. Uyğunlaşdırılan sinif (yaddaş xəritəsi) adapterin sahələrindən birinə çevrilir. Bu məntiqlidir, çünki real həyatda biz kart oxuyucunun içərisinə də bir kart daxil edirik və o da onun bir hissəsinə çevrilir. Yaddaş kartından fərqli olaraq, adapter kompüterlə ümumi interfeysə malikdir. USB kabeli var, yəni USB vasitəsilə digər cihazlara qoşula bilər. Buna görə də, proqramda bizim sinif CardReaderUSB interfeysini həyata keçirir. Bəs bu metodun daxilində nə baş verir? Və tam olaraq ehtiyacımız olan şey olur! Adapter işi yaddaş kartımıza həvalə edir. Axı, adapterin özü heç nə etmir, kart oxuyucusu müstəqil funksiyaya malik deyil. Onun işi yalnız kompüter və yaddaş kartını birləşdirməkdir ki, kart öz işini görüb faylları kopyalaya bilsin! Adapterimiz connectWithUsbCable()yaddaş kartının "ehtiyacları" üçün öz interfeysini (metodunu) təmin etməklə bunu etməyə imkan verir. Yaddaş kartından məlumatları köçürmək istəyən bir insanı simulyasiya edəcək bir növ müştəri proqramı yaradaq:
public class Main {

   public static void main(String[] args) {

       USB cardReader = new CardReader(new MemoryCard());
       cardReader.connectWithUsbCable();

   }
}
Nəticədə nə əldə etdik? Konsol çıxışı:
Карта памяти успешно вставлена!
Данные скопированы на компьютер!
Əla, tapşırığımız uğurla tamamlandı! Adapter nümunəsi haqqında məlumatı əks etdirən bəzi əlavə bağlantılar:

Abstrakt dərsləri Reader və Writer

İndi biz sevimli əyləncəmizə qayıdacağıq: giriş və çıxışla işləmək üçün bir neçə yeni dərs öyrənəcəyik :) Onların neçəsini artıq öyrənmişik, görəsən? Bu gün biz dərslər haqqında danışacağıq ReaderWriter. Niyə onlar haqqında? Çünki bu bizim əvvəlki bölməmizlə - adapterlərlə bağlı olacaq. Gəlin onlara daha ətraflı baxaq. 'a ilə başlayaq Reader. Readermücərrəd sinifdir, ona görə də biz onun obyektlərini açıq şəkildə yarada bilməyəcəyik. Amma əslində, siz onu artıq tanıyırsınız! Axı sizin yaxşı bildiyiniz siniflər onun BufferedReadervarisləridir InputStreamReader:)
public class BufferedReader extends Reader {}

public class InputStreamReader extends Reader {}
Beləliklə, bir sinif InputStreamReaderklassik adapterdir . Yəqin ki, xatırladığınız kimi, biz obyekti onun konstruktoruna ötürə bilərik InputStream. Bunun üçün çox vaxt dəyişəndən istifadə edirik System.in:
public static void main(String[] args) {

   InputStreamReader inputStreamReader = new InputStreamReader(System.in);
}
Bu nə edir InputStreamReader? Hər hansı bir adapter kimi, bir interfeysi digərinə çevirir. Bu halda, interfeys InputStream'a interfeysinə Reader'a. Əvvəlcə sinifimiz var idi InputStream. Yaxşı işləyir, lakin yalnız fərdi baytları oxuya bilər. Bundan əlavə, abstrakt sinifimiz var Reader. O, həqiqətən ehtiyacımız olan əla funksionallığa malikdir - simvolları oxuya bilir! Təbii ki, bizim bu fürsətə çox ehtiyacımız var. Ancaq burada adapterlərin adətən həll etdiyi klassik problemlə qarşılaşırıq - interfeys uyğunsuzluğu. Özünü necə göstərir? Gəlin birbaşa Oracle sənədlərinə baxaq. Budur sinif üsulları InputStream. Dizayn nümunəsi "Adapter" - 4Metodlar toplusu interfeysdir. Gördüyünüz kimi, read()bu sinifin metodu var (hətta bir neçə versiyada), lakin o, yalnız baytları oxuya bilər: ya fərdi bayt, ya da buferdən istifadə edən bir neçə bayt. Bu seçim bizə uyğun deyil - simvolları oxumaq istəyirik. Bizə lazım olan funksionallıq artıq abstrakt sinifdə həyata keçirilirReader . Bunu sənədlərdə də görmək olar. Adapter dizayn nümunəsi - 5Bununla belə, InputStream"a" və Reader"a" interfeysləri uyğun gəlmir! Gördüyünüz kimi, bütün metod tətbiqlərində read()həm ötürülən parametrlər, həm də qaytarılan dəyərlər fərqlidir. Və bu bizə lazım olan yerdir InputStreamReader! O , siniflərimiz arasında Adapter rolunu oynayacaq . Yuxarıda baxdığımız kart oxuyucusu ilə nümunədə olduğu kimi, biz "uyğunlaşdırılmış" sinif obyektini "daxili", yəni adapter sinfinin konstruktoruna keçirik. Əvvəlki nümunədə bir obyektin MemoryCardiçindən keçdik CardReader. InputStreamİndi obyekti konstruktora ötürürük InputStreamReader! Keyfiyyət olaraq InputStreambiz artıq tanış dəyişəndən istifadə edirik System.in:
public static void main(String[] args) {

   InputStreamReader inputStreamReader = new InputStreamReader(System.in);
}
Və həqiqətən də: sənədlərə baxaraq InputStreamReadergörərik ki, “uyğunlaşma” uğurlu alınıb :) İndi simvolları oxumağa imkan verən üsullarımız var. Adapter dizayn nümunəsi - 6Əvvəlcə obyektimiz System.in(klaviaturaya bağlanmış ip) buna imkan verməsə də, Adapter nümunəsini yaratmaqla dilin yaradıcıları bu problemi həll etdilər. Abstrakt sinif Reader, əksər I/O sinifləri kimi, əkiz qardaşa malikdir - Writer. Onun eyni böyük üstünlüyü var Reader- simvollarla işləmək üçün rahat interfeys təmin edir. Çıxış axınları ilə problem və onun həlli giriş axınlarında olduğu kimi görünür. OutputStreamYalnız bayt yaza bilən bir sinif var ; WriterSimvollarla işləyə bilən mücərrəd sinif və bir-birinə uyğun gəlməyən iki interfeys var . Bu problem yenidən Adapter nümunəsi ilə uğurla həll olunur. Bir sinifdən istifadə edərək, iki sinif interfeysini bir- birinə OutputStreamWriterasanlıqla "uyğunlaşdıra" bilərik . Və konstruktorda bir bayt axını aldıqdan sonra , köməyi ilə bayt deyil, simvol yaza bilərik! WriterOutputStreamOutputStreamOutputStreamWriter
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();
   }
}
Faylımıza 32144 - 綐 kodlu simvol yazdıq, bununla da baytlarla işləmək ehtiyacını aradan qaldırdıq :) Bu günə qədər bu qədər, növbəti mühazirələrdə görüşənədək! :)
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION