CodeGym /Java blog /Véletlen /Adapter tervezési minta
John Squirrels
Szint
San Francisco

Adapter tervezési minta

Megjelent a csoportban
Szia! Ma egy fontos új témát fogunk érinteni: a tervezési mintákat . Mik ezek a minták? Szerintem ismerned kell a " ne találd fel újra a kereket " kifejezést. A programozásban, mint sok más területen, számos gyakori helyzet adódik. A szoftverfejlesztés fejlődésével mindegyikhez készültek működő kész megoldások. Ezeket a megoldásokat tervezési mintáknak nevezzük. Megállapodás szerint a minta valamilyen megoldás, amely így van megfogalmazva: "ha X-et kell tennie a programban, akkor ez a legjobb módja annak". Rengeteg minta van. Nekik készült a kiváló "Head First Design Patterns" könyv, amelyet mindenképpen érdemes megismerned. Adapter tervezési minta - 2Tömören fogalmazva, egy minta egy közös problémából és egy megfelelő megoldásból áll, amely egyfajta szabványnak tekinthető. A mai leckében a következő minták egyikével fogunk találkozni: Adapter. A neve mindent elárul, és a való életben is sokszor találkozott már adapterekkel. A leggyakoribb adapterek a kártyaolvasók, amelyek sok számítógépen és laptopon megtalálhatók. Adapter tervezési minta - 3Tegyük fel, hogy van valamilyen memóriakártyánk. Tehát mi a probléma? Nem tudja, hogyan kommunikáljon a számítógéppel. Nincs közös felületük. A számítógép USB porttal rendelkezik, de nem tudjuk belehelyezni a memóriakártyát. A kártya nem csatlakoztatható a számítógéphez, így fotóinkat, videóinkat és egyéb adatainkat nem tudjuk elmenteni. A kártyaolvasó egy adapter, amely megoldja ezt a problémát. Elvégre USB kábel van hozzá! Magával a kártyával ellentétben a kártyaolvasó csatlakoztatható a számítógéphez. Közös interfészük van a számítógéppel: USB. Lássuk, hogyan is néz ki ez a gyakorlatban:

public interface USB { 

   void connectWithUsbCable(); 
}
Ez a mi USB-interfészünk, amely egyetlen USB-csatlakozási móddal rendelkezik.

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!"); 
   } 
}
Ez a mi osztályunk, amely a memóriakártyát képviseli. Már megvan a 2 módszer, amire szükségünk van, de itt van a probléma: Nem valósítja meg az USB interfészt. A kártya nem helyezhető be az USB-portba.

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(); 
   } 
}
És itt az adapterünk! Mit csinál aCardReaderosztály dolgát, és pontosan mitől lesz adapter? Minden egyszerű. Az adaptálandó osztály (MemoryCard) az adapter egyik mezőjévé válik. Ennek van értelme. Ha a valóságban egy memóriakártyát teszünk a kártyaolvasóba, az is annak részévé válik. A memóriakártyával ellentétben az adapter megoszt egy interfészt a számítógéppel. USB kábellel rendelkezik, azaz USB-n keresztül csatlakoztatható más eszközökhöz. Ezért valósítja meg a CardReader osztályunk az USB interfészt. De mi történik pontosan ebben a módszerben? Pontosan annak, aminek meg kell történnie! Az adapter a memóriakártyánkra delegálja a munkát. Valójában az adapter nem csinál semmit. A kártyaolvasónak nincs önálló funkciója. Feladata csak a számítógép és a memóriakártya összekapcsolása, hogy a kártya elvégezhesse a feladatát – fájlok másolását!connectWithUsbCable()módszer) a memóriakártya „szükségleteinek” kielégítésére. Hozzunk létre egy kliens programot, amely szimulálja azt a személyt, aki adatokat szeretne másolni a memóriakártyáról:

public class Main { 

   public static void main(String[] args) { 

       USB cardReader = new CardReader(new MemoryCard()); 
       cardReader.connectWithUsbCable(); 
   } 
}
Szóval mit kaptunk? Konzol kimenet:

Memory card successfully inserted! 
The data has been copied to the computer!
Kiváló. Célunkat elértük! Itt található egy link az adaptermintával kapcsolatos információkat tartalmazó videóhoz:

Olvasó és író absztrakt órák

Most visszatérünk kedvenc tevékenységünkhöz: néhány új kurzus megismerése a bemenettel és a kimenettel való munkavégzéshez :) Kíváncsi vagyok, mennyit tanultunk már. Reader Ma a és az osztályokról fogunk beszélni Writer. Miért pont ezek az osztályok? Mert ezek az adapterekről szóló előző részünkhöz kapcsolódnak. Vizsgáljuk meg őket részletesebben. Kezdjük azzal  Reader. Readeregy absztrakt osztály, így nem tudunk explicit módon objektumokat létrehozni.   De valójában már ismeri! Hiszen jól ismered a BufferedReaderés InputStreamReaderosztályokat, amelyek a leszármazottai :)

public class BufferedReader extends Reader { 
… 
} 

public class InputStreamReader extends Reader { 
… 
}
Az InputStreamReaderosztály egy klasszikus adapter. Amint valószínűleg emlékszel, átadhatunk egy InputStreamobjektumot a konstruktorának. Ehhez általában a System.inkövetkező változót használjuk:

public static void main(String[] args) { 

   InputStreamReader inputStreamReader = new InputStreamReader(System.in); 
}
De mit InputStreamReadercsinál? Mint minden adapter, ez is átalakítja az egyik interfészt a másikba.  Ebben az esetben az InputStreaminterfész az interfészhez Reader. Kezdetben megvan az InputStreamosztály. Jól működik, de csak egyes bájtok olvasására használható. Ezen kívül van egy Readerabsztrakt osztályunk. Van néhány nagyon hasznos funkciója – tudja, hogyan kell karaktereket olvasni! Erre a képességre mindenképpen szükségünk van. De itt szembesülünk azzal a klasszikus problémával, amelyet általában adapterek oldanak meg – az inkompatibilis interfészek. Az mit jelent? Vessünk egy pillantást az Oracle dokumentációjára. Itt vannak az InputStreamosztály metódusai. Adapter tervezési minta - 4Egy interfész pontosan a metódusok halmaza. Amint látja, ennek az osztálynak aread()módszer (valójában néhány változat), de csak bájtokat tud olvasni: vagy egyedi bájtokat, vagy puffer segítségével több bájtot. De ez a lehetőség nem felel meg nekünk – karaktereket szeretnénk olvasni. Szükségünk van az Readerabsztrakt osztályban már megvalósított funkciókra . Ezt láthatjuk a dokumentációban is. A és  interfészek Adapter tervezési minta - 5azonban nem kompatibilisek! Amint látható, a metódus minden implementációja eltérő paraméterekkel és visszatérési értékekkel rendelkezik. És itt van szükségünk ! Adapterként fog működni az osztályaink között. InputStreamReaderread()InputStreamReaderMint a fentebb vizsgált kártyaolvasó példájában, az adaptált osztály egy példányát az adapter osztályba helyezzük, azaz átadunk egyet a konstruktorának. Az előző példában egy MemoryCardobjektumot helyeztünk a belsejébe CardReader. Most átadunk egy InputStream tárgyat a InputStreamReaderkivitelezőnek! System.inIsmert változónkat a következőképpen használjuk InputStream:

public static void main(String[] args) { 

   InputStreamReader inputStreamReader = new InputStreamReader(System.in); 
}
És valóban, átnézve a dokumentációt InputStreamReader, láthatjuk, hogy az adaptáció sikerült :) Most már a karakterek olvasására szolgáló módszerek állnak rendelkezésünkre. Adapter tervezési minta - 6És bár az System.inobjektumunk (a billentyűzethez kötött folyam) ezt kezdetben nem tette lehetővé, a nyelv készítői az adapterminta megvalósításával megoldották ezt a problémát. Az Readerabsztrakt osztálynak, mint a legtöbb I/O osztálynak, van egy ikertestvére –  Writer. Ugyanolyan nagy előnye van, mint  Reader — kényelmes felületet biztosít a karakterekkel való munkavégzéshez. A kimeneti adatfolyamoknál a probléma és annak megoldása ugyanúgy néz ki, mint a bemeneti adatfolyamoknál. Van egy OutputStreamosztály, ami csak bájtokat tud írni, van egyWriterabsztrakt osztály, amely tudja, hogyan kell dolgozni a karakterekkel, és van két nem kompatibilis felület. Ezt a problémát ismét megoldja az adapter mintája. Az osztály segítségével könnyen  egymáshoz OutputStreamWriterigazíthatjuk az Writer és  osztályok két interfészét. OutputStreamMiután átadtunk egy byte-folyamot a konstruktornak, a bájt helyett karakterek írásához OutputStreamhasználhatjuk a -t!OutputStreamWriter

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();
   } 
}
A 32144 (綐) kódú karaktert a fájlunkba írtuk, így nem kell bájtokkal dolgozni :) Mára ennyi. Találkozunk a következő leckéken! :)
Hozzászólások
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION