CodeGym /Java Blog /Random /Pattern ng disenyo ng adaptor
John Squirrels
Antas
San Francisco

Pattern ng disenyo ng adaptor

Nai-publish sa grupo
Hi! Ngayon ay tatalakayin natin ang isang mahalagang bagong paksa: mga pattern ng disenyo . Ano ang mga pattern na ito? Sa tingin ko dapat alam mo ang expression na " don't reinvent the wheel ". Sa programming, tulad ng sa maraming iba pang mga lugar, mayroong isang malaking bilang ng mga karaniwang sitwasyon. Habang umuunlad ang software development, ang mga handa na solusyon na gumagana ay nilikha para sa bawat isa sa kanila. Ang mga solusyong ito ay tinatawag na mga pattern ng disenyo. Sa pamamagitan ng convention, ang isang pattern ay ilang solusyon na binabalangkas tulad nito: "kung kailangan mong gawin ang X sa iyong programa, kung gayon ito ang pinakamahusay na paraan upang gawin ito". Mayroong maraming mga pattern. Ang napakahusay na aklat na "Head First Design Patterns", na dapat mong maging pamilyar, ay nakatuon sa kanila. Pattern ng disenyo ng adaptor - 2Sa madaling salita, ang isang pattern ay binubuo ng isang karaniwang problema at isang kaukulang solusyon na maaaring ituring na isang uri ng pamantayan. Sa aralin ngayon, matutugunan natin ang isa sa mga pattern na ito: Adapter. Nakasaad sa pangalan ang lahat, at maraming beses kang nakatagpo ng mga adaptor sa totoong buhay. Ang ilan sa mga pinakakaraniwang adapter ay ang mga card reader na mayroon ang maraming mga computer at laptop. Pattern ng disenyo ng adaptor - 3Ipagpalagay na mayroon kaming isang uri ng memory card. So anong problema? Hindi nito alam kung paano makipag-ugnayan sa computer. Hindi sila nagbabahagi ng isang karaniwang interface. Ang computer ay may USB port, ngunit hindi namin maipasok ang memory card dito. Ang card ay hindi maisaksak sa computer, kaya hindi namin mai-save ang aming mga larawan, video, at iba pang data. Ang card reader ay isang adaptor na lumulutas sa problemang ito. Pagkatapos ng lahat, mayroon itong USB cable! Hindi tulad ng card mismo, ang card reader ay maaaring isaksak sa computer. Ibinabahagi nila ang isang karaniwang interface sa computer: USB. Tingnan natin kung ano ang hitsura nito sa pagsasanay:

public interface USB { 

   void connectWithUsbCable(); 
}
Ito ang aming USB interface na may isang paraan lamang para sa pagkonekta sa pamamagitan ng 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!"); 
   } 
}
Ito ang aming klase na kumakatawan sa memory card. Mayroon na itong 2 pamamaraan na kailangan namin, ngunit narito ang problema: Hindi nito ipinapatupad ang USB interface. Ang card ay hindi maaaring ipasok sa USB port.

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(); 
   } 
}
At narito ang aming adaptor! Ano ang ginagawa ngCardReaderklase at ano ang eksaktong ginagawa itong isang adaptor? Simple lang lahat. Ang klase na iniangkop (MemoryCard) ay nagiging isa sa mga field ng adapter. Ito ay may katuturan. Kapag naglagay tayo ng memory card sa loob ng isang card reader sa totoong buhay, ito rin ay nagiging bahagi nito. Hindi tulad ng memory card, ang adaptor ay nagbabahagi ng isang interface sa computer. Mayroon itong USB cable, ibig sabihin, maaari itong ikonekta sa iba pang mga device sa pamamagitan ng USB. Iyon ang dahilan kung bakit ipinapatupad ng aming klase ng CardReader ang USB interface. Ngunit ano ang eksaktong nangyayari sa loob ng pamamaraang ito? Eksakto ang kailangan nating mangyari! Idelegate ng adapter ang trabaho sa aming memory card. Sa katunayan, ang adaptor ay walang ginagawa mismo. Ang isang card reader ay walang anumang independiyenteng pag-andar. Ang trabaho nito ay ikonekta lamang ang computer at memory card upang payagan ang card na gawin ang trabaho nito — pagkopya ng mga file!connectWithUsbCable()paraan) upang matugunan ang "mga pangangailangan" ng memory card. Gumawa tayo ng ilang programa ng kliyente na gayahin ang isang taong gustong kumopya ng data mula sa isang memory card:

public class Main { 

   public static void main(String[] args) { 

       USB cardReader = new CardReader(new MemoryCard()); 
       cardReader.connectWithUsbCable(); 
   } 
}
Kaya ano ang nakuha namin? Output ng console:

Memory card successfully inserted! 
The data has been copied to the computer!
Magaling. Naabot namin ang aming layunin! Narito ang isang link sa isang video na may impormasyon tungkol sa pattern ng Adapter:

Mga abstract na klase ng Reader at Writer

Ngayon ay babalik tayo sa paborito nating aktibidad: pag-aaral tungkol sa ilang bagong klase para sa pagtatrabaho sa input at output :) Siguro kung ilan na ang natutunan natin. Ngayon ay pag-uusapan natin ang tungkol sa Reader at Writermga klase. Bakit partikular ang mga klase? Dahil ang mga ito ay nauugnay sa aming nakaraang seksyon tungkol sa mga adaptor. Suriin natin ang mga ito nang mas detalyado. Magsisimula tayo sa  Reader. Readeray isang abstract na klase, kaya hindi kami makakagawa ng mga bagay nang tahasan.   Ngunit talagang pamilyar ka na dito! Sabagay, kilalang-kilala mo ang BufferedReaderat InputStreamReadermga klase, na mga inapo nito :)

public class BufferedReader extends Reader { 
… 
} 

public class InputStreamReader extends Reader { 
… 
}
Ang InputStreamReaderklase ay isang klasikong adaptor. Tulad ng malamang na natatandaan mo, maaari naming ipasa ang isang InputStreambagay sa constructor nito. Upang gawin ito, karaniwang ginagamit namin ang System.invariable:

public static void main(String[] args) { 

   InputStreamReader inputStreamReader = new InputStreamReader(System.in); 
}
Ngunit ano ang InputStreamReaderginagawa? Tulad ng bawat adaptor, nagko-convert ito ng isang interface sa isa pa.  Sa kasong ito, ang InputStreaminterface sa Readerinterface. Sa simula, may klase kami InputStream. Gumagana ito nang maayos, ngunit magagamit mo lamang ito upang magbasa ng mga indibidwal na byte. Bilang karagdagan, mayroon kaming Readerabstract na klase. Mayroon itong napaka-kapaki-pakinabang na pag-andar — marunong itong magbasa ng mga character! Tiyak na kailangan natin ang kakayahang ito. Ngunit narito, nahaharap tayo sa klasikong problema na kadalasang nalulutas ng mga adaptor — mga hindi tugmang interface. Anong ibig sabihin niyan? Tingnan natin ang dokumentasyon ng Oracle. Narito ang mga pamamaraan ng InputStreamklase. Pattern ng disenyo ng adaptor - 4Ang isang hanay ng mga pamamaraan ay tiyak kung ano ang isang interface. Tulad ng makikita mo, ang klase na ito ay may isangread()paraan (sa katunayan, ilang mga variant), ngunit maaari lamang itong magbasa ng mga byte: alinman sa mga indibidwal na byte, o ilang mga byte gamit ang isang buffer. Ngunit hindi angkop sa amin ang opsyong ito — gusto naming magbasa ng mga character. Kailangan namin ang functionality na naipatupad na sa Readerabstract class . Makikita rin natin ito sa dokumentasyon. Pattern ng disenyo ng adaptor - 5Gayunpaman, ang InputStreamat  Readermga interface ay hindi tugma! Tulad ng nakikita mo, ang bawat pagpapatupad ng read()pamamaraan ay may iba't ibang mga parameter at mga halaga ng pagbabalik. At ito ay kung saan kailangan namin InputStreamReader! Ito ay magsisilbing adaptor sa pagitan ng aming mga klase. Tulad ng halimbawa sa card reader, na aming isinasaalang-alang sa itaas, naglalagay kami ng isang halimbawa ng klase na iniangkop "sa loob" ng klase ng adaptor, ibig sabihin, ipinapasa namin ang isa sa tagabuo nito. Sa nakaraang halimbawa, naglalagay kami ng isang MemoryCardbagay sa loob CardReader. Ngayon kami ay nagpapasa ng isang InputStream bagay sa InputStreamReaderconstructor! Ginagamit namin ang aming pamilyar System.inna variable bilang ang InputStream:

public static void main(String[] args) { 

   InputStreamReader inputStreamReader = new InputStreamReader(System.in); 
}
At sa katunayan, sa pagtingin sa dokumentasyon para sa InputStreamReader, makikita natin na ang adaptasyon ay nagtagumpay :) Ngayon ay mayroon na tayong mga paraan upang basahin ang mga character na magagamit natin. At bagama't hindi ito pinahintulutan ng Pattern ng disenyo ng adaptor - 6aming object (ang stream na nakatali sa keyboard), ang mga tagalikha ng wika ay nilutas ang problemang ito sa pamamagitan ng pagpapatupad ng adapter pattern. System.inAng Readerabstract na klase, tulad ng karamihan sa mga klase ng I/O, ay may kambal na kapatid na lalaki —  Writer. Ito ay may parehong malaking kalamangan tulad ng  Reader — ito ay nagbibigay ng isang maginhawang interface para sa pagtatrabaho sa mga character. Sa mga output stream, ang problema at ang solusyon nito ay kamukha ng mga input stream. Mayroong isang OutputStreamklase na maaari lamang magsulat ng mga byte, mayroong isangWriterabstract class na alam kung paano magtrabaho sa mga character, at mayroong dalawang hindi magkatugma na mga interface. Ang problemang ito ay muling nalutas sa pamamagitan ng pattern ng adaptor. Ginagamit namin ang OutputStreamWriterklase upang madaling iakma ang dalawang interface ng Writer at  OutputStream mga klase sa isa't isa. Pagkatapos magpasa ng isang OutputStreambyte stream sa constructor, maaari tayong gumamit ng isang OutputStreamWriterpara magsulat ng mga character kaysa sa mga 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();
   } 
}
Isinulat namin ang character na may code 32144 (綐) sa aming file, na inaalis ang pangangailangan na gumana sa mga byte :) Iyon lang para sa ngayon. Magkita-kita tayo sa susunod na mga aralin! :)
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION