"Szia, Amigo! Ma elmondok néhány érdekességet a BufferedInputStream osztályról, de kezdjük a "csomagolókkal " és egy " zacskó cukorral ".

– Mit értesz „csomagoló” és „zacskó cukor” alatt?

– Ezek metaforák. Figyelj. Szóval…

A "wrapper" (vagy "dekorátor") tervezési minta egy meglehetősen egyszerű és kényelmes mechanizmus az objektumok funkcionalitásának kiterjesztésére az öröklődés nélkül.

BufferedInputStream – 1

Tegyük fel, hogy van egy Cat osztályunk két metódussal: getName és setName:

Java kód Leírás
class Cat
{
 private String name;
 public Cat(String name)
 {
  this.name = name;
 }
 public String getName()
 {
  return this.name;
 }
 public void setName(String name)
 {
  this.name = name;
 }
}
A Cat osztálynak két metódusa van: getName és setName
public static void main(String[] args)
{
 Cat cat = new Cat("Oscar");

 printName(cat);
}

public static void printName(Cat cat)
{
 System.out.println(cat.getName());
}
Példa arra, hogyan lehet használni.

Az „Oscar” felirat jelenik meg a konzolon.

Tegyük fel, hogy el kell fognunk egy módszerhívást egy macska objektumon, és esetleg apró változtatásokat kell végrehajtanunk. Ehhez be kell csomagolnunk a saját wrapper osztályába.

Ha saját kódunkat akarjuk "burkolni" egy objektum metódushívásai köré, akkor:

1) Hozzuk létre a saját burkoló osztályunkat, és örököljük ugyanazt az osztályt/felületet, mint a csomagolandó objektum.

2) Adjuk át a becsomagolandó tárgyat osztályunk konstruktorának.

3) Az új osztályunk összes metódusának felülírása. Hívja meg a becsomagolt objektum metódusait a felülírt metódusokon belül.

4) Végezze el a kívánt változtatásokat: módosítsa a metódushívások tevékenységét, módosítsa a paramétereiket és/vagy tegyen valami mást.

Az alábbi példában elfogjuk a Cat objektum getName metódusának hívását, és kissé megváltoztatjuk a visszatérési értékét.

Java kód Leírás
class Cat
{
 private String name;
 public Cat(String name)
 {
  this.name = name;
 }
 public String getName()
 {
  return this.name;
 }
 public void setName(String name)
 {
  this.name = name;
 }
}
A Cat osztály két metódust tartalmaz: getName és setName.
class CatWrapper extends Cat
{
 private Cat original;
 public CatWrapper (Cat cat)
 {
  super(cat.getName());
  this.original = cat;
 }

 public String getName()
 {
  return "A cat named " + original.getName();
 }

 public void setName(String name)
 {
  original.setName(name);
 }
}
A csomagoló osztály. Az osztály nem tárol semmilyen adatot, kivéve az eredeti objektumra való hivatkozást.
Az osztály képes hívásokat "dobni" a konstruktornak átadott eredeti objektumra (setName). Ezenkívül „elkaphatja” ezeket a hívásokat, és módosíthatja paramétereiket és/vagy eredményeiket .
public static void main(String[] args)
{
 Cat cat = new Cat("Oscar");
 Cat catWrap = new CatWrapper (cat);
 printName(catWrap);
}

public static void printName(Cat named)
{
 System.out.println(named.getName());
}
Példa arra, hogyan lehet használni.

"Egy Oscar nevű macska".
megjelenik a konzolon

Más szóval, minden eredeti objektumot csendben lecserélünk egy burkoló objektumra, amely az eredeti objektumra mutató hivatkozást kap. A burkoló minden metódushívása az eredeti objektumhoz kerül, és minden úgy fut, mint a karikacsapás.

"Szeretem. A megoldás egyszerű és funkcionális."

"Elmesélek egy "zacskó cukorról" is. Ez inkább metafora, mint tervezési minta. A puffer és a pufferelés szó metaforája. Mi az a pufferelés, és miért van rá szükségünk?"

BufferedInputStream – 2

Tegyük fel, hogy ma Rishi-n a sor, hogy főzzön, és te segítesz neki. Rishi még nincs itt, de szeretnék teát inni. Megkérem, hogy hozzon nekem egy kanál cukrot. Kimész a pincébe és találsz egy zacskó cukrot. Elhozhatod nekem az egész táskát, de nincs szükségem a táskára. Csak egy kanál kell. Aztán, mint egy jó robot, veszel egy kanállal, és hozod nekem. Hozzáadom a teához, de még mindig nem elég édes. És megkérlek, hogy hozz még egyet. Ismét menj az alagsorba, és hozz még egy kanállal. Aztán jön Ellie, és megkérlek, hogy hozz neki cukrot... Mindez túl sokáig tart és nem hatékony.

Rishi jön, látja mindezt, és megkér, hogy hozzon neki egy cukorral teli cukros tálat. Aztán Ellie-vel elkezdünk cukrot kérni Rishitől. Egyszerűen a cukortartóból tálalja fel nekünk, és ennyi.

Ami Rishi megjelenése után történt, azt pufferelésnek nevezik : a cukortartó puffer. A pufferelésnek köszönhetően a „kliensek” kis részletekben olvashatják ki az adatokat a pufferből , míg a puffer – idő és erőfeszítés megtakarítása érdekében – nagy részletekben olvassa be azokat a forrásból .

"Ez egy klassz példa, Kim. Tökéletesen megértem. Egy kanál cukor kérése olyan, mintha egy bájtot olvasnánk egy adatfolyamból."

"Pontosan. A BufferedInputStream osztály a pufferelt burkoló klasszikus példája. Becsomagolja az InputStream osztályt. Az adatokat az eredeti InputStreamből nagy blokkokban olvassa be egy pufferbe, majd darabonként húzza ki a pufferből, ahogy mi olvass belőle."

"Nagyon jó. Minden világos. Vannak pufferek az íráshoz?"

"Oh biztos."

– Talán egy példa?

"Képzeljen el egy szemeteskukát. Ahelyett, hogy minden alkalommal kimenne a szemetet egy szemétégetőbe tenni, egyszerűen csak dobja a kukába. Aztán Bubba kéthetente egyszer kiviszi a kukát. Klasszikus puffer."

– Milyen érdekes! És egyébként sokkal tisztább, mint egy zacskó cukor.

"A flush() módszer pedig olyan, mintha azonnal kivenné a szemetet. Használhatod még a vendégek érkezése előtt."