CodeGym /Java blog /Tilfældig /Adapter design mønster
John Squirrels
Niveau
San Francisco

Adapter design mønster

Udgivet i gruppen
Hej! I dag vil vi berøre et vigtigt nyt emne: designmønstre . Hvad er disse mønstre? Jeg tror, ​​du skal kende udtrykket " opfind ikke hjulet igen ". Inden for programmering, som på mange andre områder, er der en lang række almindelige situationer. Efterhånden som softwareudviklingen har udviklet sig, er der skabt færdige løsninger, der virker til hver af dem. Disse løsninger kaldes designmønstre. Konventionelt er et mønster en løsning formuleret sådan: "hvis du skal lave X i dit program, så er dette den bedste måde at gøre det på". Der er mange mønstre. Den fremragende bog "Head First Design Patterns", som du bestemt bør stifte bekendtskab med, er dedikeret til dem. Adapterdesignmønster - 2Kort fortalt består et mønster af et fælles problem og en tilsvarende løsning, der kan betragtes som en slags standard. I dagens lektion vil vi møde et af disse mønstre: Adapter. Dens navn siger det hele, og du har stødt på adaptere mange gange i det virkelige liv. Nogle af de mest almindelige adaptere er de kortlæsere, som mange computere og bærbare computere har. Adapterdesignmønster - 3Antag, at vi har en slags hukommelseskort. Så hvad er problemet? Den ved ikke, hvordan den interagerer med computeren. De deler ikke en fælles grænseflade. Computeren har en USB-port, men vi kan ikke sætte hukommelseskortet i den. Kortet kan ikke sættes i computeren, så vi kan ikke gemme vores billeder, videoer og andre data. En kortlæser er en adapter, der løser dette problem. Den har jo et USB-kabel! I modsætning til selve kortet kan kortlæseren tilsluttes computeren. De deler en fælles grænseflade med computeren: USB. Lad os se, hvordan det ser ud i praksis:

public interface USB { 

   void connectWithUsbCable(); 
}
Dette er vores USB-interface med kun én metode til tilslutning via 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!"); 
   } 
}
Dette er vores klasse, der repræsenterer hukommelseskortet. Den har allerede de 2 metoder, vi har brug for, men her er problemet: Den implementerer ikke USB-grænsefladen. Kortet kan ikke indsættes i USB-porten.

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(); 
   } 
}
Og her er vores adapter! Hvad gørCardReaderklasse gør, og hvad gør det præcist til en adapter? Det hele er enkelt. Klassen, der tilpasses (MemoryCard), bliver et af adapterens felter. Dette giver mening. Når vi sætter et hukommelseskort i en kortlæser i det virkelige liv, bliver det også en del af det. I modsætning til hukommelseskortet deler adapteren en grænseflade med computeren. Den har et USB-kabel, dvs den kan tilsluttes andre enheder via USB. Det er derfor, vores CardReader-klasse implementerer USB-grænsefladen. Men hvad sker der præcist i denne metode? Præcis hvad vi skal til at ske! Adapteren delegerer arbejdet til vores hukommelseskort. Faktisk gør adapteren ikke noget selv. En kortlæser har ikke nogen selvstændig funktionalitet. Dens opgave er kun at forbinde computeren og hukommelseskortet for at tillade kortet at gøre sit arbejde - kopiering af filer!connectWithUsbCable()metode) for at opfylde hukommelseskortets "behov". Lad os lave et klientprogram, der simulerer en person, der ønsker at kopiere data fra et hukommelseskort:

public class Main { 

   public static void main(String[] args) { 

       USB cardReader = new CardReader(new MemoryCard()); 
       cardReader.connectWithUsbCable(); 
   } 
}
Så hvad fik vi? Konsoludgang:

Memory card successfully inserted! 
The data has been copied to the computer!
Fremragende. Vi nåede vores mål! Her er et link til en video med information om adaptermønsteret:

Læser og forfatter abstrakt klasser

Nu vender vi tilbage til vores yndlingsaktivitet: at lære om et par nye klasser til at arbejde med input og output :) Jeg spekulerer på, hvor mange vi allerede har lært om. I dag vil vi tale om Reader og Writerklasser. Hvorfor netop de klasser? Fordi de er relateret til vores tidligere afsnit om adaptere. Lad os undersøge dem mere detaljeret. Vi starter med  Reader. Readerer en abstrakt klasse, så vi vil ikke være i stand til at oprette objekter eksplicit.   Men du er faktisk allerede bekendt med det! Du er jo godt bekendt med klasserne BufferedReaderog InputStreamReader, som er dens efterkommere :)

public class BufferedReader extends Reader { 
… 
} 

public class InputStreamReader extends Reader { 
… 
}
Klassen InputStreamReaderer en klassisk adapter. Som du sikkert husker, kan vi videregive et InputStreamobjekt til dets konstruktør. For at gøre dette bruger vi normalt System.invariablen:

public static void main(String[] args) { 

   InputStreamReader inputStreamReader = new InputStreamReader(System.in); 
}
Men hvad InputStreamReadergør? Som enhver adapter konverterer den en grænseflade til en anden.  I dette tilfælde grænsefladen InputStreamtil Readergrænsefladen. I første omgang har vi InputStreamklassen. Det fungerer godt, men du kan kun bruge det til at læse individuelle bytes. Derudover har vi en Readerabstrakt klasse. Det har nogle meget nyttige funktioner - det ved, hvordan man læser tegn! Vi har bestemt brug for denne evne. Men her står vi over for det klassiske problem, der normalt løses af adaptere - inkompatible grænseflader. Hvad betyder det? Lad os tage et kig på Oracle-dokumentationen. Her er klassens metoder InputStream. Adapterdesignmønster - 4Et sæt metoder er præcis, hvad en grænseflade er. Som du kan se, har denne klasse enread()metode (faktisk nogle få varianter), men den kan kun læse bytes: enten individuelle bytes eller flere bytes ved hjælp af en buffer. Men denne mulighed passer ikke os - vi vil gerne læse karakterer. Vi har brug for den funktionalitet, der allerede er implementeret i den Readerabstrakte klasse . Det kan vi også se i dokumentationen. Adapterdesignmønster - 5Men grænsefladerne InputStreamog  Readerer inkompatible! Som du kan se, har hver implementering af read()metoden forskellige parametre og returværdier. Og det er her, vi har brug for InputStreamReader! Det vil fungere som en adapter mellem vores klasser. Som i eksemplet med kortlæseren, som vi overvejede ovenfor, sætter vi en instans af klassen, der er tilpasset "inde i" adapterklassen, dvs. vi sender en til dens konstruktør. I det foregående eksempel satte vi et MemoryCardobjekt ind i CardReader. Nu sender vi et InputStream objekt til InputStreamReaderkonstruktøren! Vi bruger vores velkendte System.invariabel som InputStream:

public static void main(String[] args) { 

   InputStreamReader inputStreamReader = new InputStreamReader(System.in); 
}
Og faktisk, ser vi på dokumentationen for InputStreamReader, kan vi se, at tilpasningen lykkedes :) Nu har vi metoder til at læse karakterer til vores rådighed. Adapterdesignmønster - 6Og selvom vores System.inobjekt (strømmen bundet til tastaturet) oprindeligt ikke tillod dette, løste sprogets skabere dette problem ved at implementere adaptermønsteret. Den Readerabstrakte klasse har ligesom de fleste I/O-klasser en tvillingebror —  Writer. Det har den samme store fordel som  Reader — det giver en praktisk grænseflade til at arbejde med karakterer. Med outputstrømme ser problemet og dets løsning ud på samme måde som med inputstrømme. Der er en OutputStreamklasse, der kun kan skrive bytes, der er enWriterabstrakt klasse, der ved, hvordan man arbejder med tegn, og der er to inkompatible grænseflader. Dette problem er igen løst af adaptermønsteret. Vi bruger OutputStreamWriterklassen til nemt at tilpasse de to grænseflader af Writer og  OutputStream klasserne til hinanden. Efter at have sendt en OutputStreambytestrøm til konstruktøren, kan vi bruge en OutputStreamWritertil at skrive tegn i stedet for bytes!

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();
   } 
}
Vi skrev tegnet med kode 32144 (綐) til vores fil, hvilket eliminerede behovet for at arbejde med bytes :) Det var det for i dag. Vi ses i de næste lektioner! :)
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION