"Hei, Amigo! I dag skal jeg fortelle deg noen interessante ting om BufferedInputStream-klassen, men la oss starte med « wraps » og en « pose sukker ».

«Hva mener du med «omslag» og «sukkerpose»?»

"Dette er metaforer. Hør. Så..."

«Wrapper» (eller «decorator») designmønsteret er en ganske enkel og praktisk mekanisme for å utvide objektfunksjonaliteten uten å bruke arv.

BufferedInputStream - 1

Anta at vi har en Cat-klasse med to metoder: getName og setName:

Java-kode Beskrivelse
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;
 }
}
Cat-klassen har to metoder: getName og 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());
}
Et eksempel på hvordan det kan brukes.

«Oscar» vil vises på konsollen.

Anta at vi må avskjære et metodekall på et katteobjekt og kanskje gjøre noen små endringer. For dette må vi pakke den inn i sin egen innpakningsklasse.

Hvis vi vil "pakke" vår egen kode rundt metodekallene på et objekt, må vi:

1) Lag vår egen wrapper-klasse og arv fra samme klasse/grensesnitt som objektet som skal pakkes inn.

2) Send objektet som skal pakkes til klassens konstruktør.

3) Overstyr alle metoder i vår nye klasse. Påkall metodene til det innpakkede objektet i hver av de overstyrte metodene.

4) Gjør hvilke endringer du vil: endre hva metodekallene gjør, endre parameterne deres og/eller gjør noe annet.

I eksemplet nedenfor fanger vi opp kall til et Cat-objekts getName-metode og endrer returverdien litt.

Java-kode Beskrivelse
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;
 }
}
Cat-klassen inneholder to metoder: getName og 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);
 }
}
Innpakningsklassen. Klassen lagrer ingen data bortsett fra en referanse til det opprinnelige objektet.
Klassen er i stand til å "kaste" kall til det originale objektet (setName) sendt til konstruktøren. Den kan også "fange" disse anropene og endre parametrene og/eller resultatene deres .
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());
}
Et eksempel på hvordan det kan brukes.

«En katt som heter Oscar».
vil vises på konsollen

Med andre ord erstatter vi hvert originalobjekt med et innpakningsobjekt, som mottar en lenke til det originale objektet. Alle metodeanrop på wrapperen videresendes til det originale objektet, og alt går som smurt.

"Jeg liker det. Løsningen er enkel og funksjonell."

"Jeg skal også fortelle deg om en «pose sukker». Dette er en metafor i stedet for et designmønster. En metafor for ordet buffer og buffering. Hva er buffering og hvorfor trenger vi det?"

BufferedInputStream - 2

La oss si at i dag er det Rishis tur til å lage mat, og du hjelper ham. Rishi er ikke her ennå, men jeg vil drikke te. Jeg ber deg ta med meg en skje sukker. Du går i kjelleren og finner en pose sukker. Du kan ta med meg hele posen, men jeg trenger ikke posen. Jeg trenger bare en skje. Så, som en god robot, tar du en skje og bringer den til meg. Jeg legger det til teen, men det er fortsatt ikke søtt nok. Og jeg ber deg ta med en til. Du går igjen i kjelleren og tar med enda en skje. Så kommer Ellie, og jeg ber deg ta med sukker til henne... Alt dette tar for lang tid og er ineffektivt.

Rishi kommer, ser alt dette, og ber deg ta med en sukkerskål full av sukker. Så begynner Ellie og jeg å spørre Rishi om sukker. Han serverer det rett og slett til oss fra sukkerbollen, og det er alt.

Det som skjedde etter at Rishi dukket opp kalles buffering : sukkerbollen er en buffer. Takket være buffering kan "klienter" lese data fra en buffer i små porsjoner , mens bufferen, for å spare tid og krefter, leser dem fra kilden i store porsjoner .

"Det er et kult eksempel, Kim. Jeg forstår det perfekt. Forespørselen om en skje sukker er som å lese en byte fra en bekk."

"Akkurat. BufferedInputStream- klassen er et klassisk eksempel på en bufret wrapper. Den pakker inn InputStream-klassen. Den leser data fra den originale InputStream i store blokker inn i en buffer, og trekker den deretter ut av bufferen stykke for stykke etter hvert som vi les fra det."

"Veldig bra. Alt er klart. Er det buffere for å skrive?"

"Sikkert."

"Kanskje et eksempel?"

"Se for deg en søppelbøtte. I stedet for å gå ut for å sette søppel i en forbrenningsovn hver gang, kaster du den bare i søppelbøtta. Da tar Bubba dunken ut en gang annenhver uke. En klassisk buffer."

"Så interessant! Og mye klarere enn en pose sukker, forresten."

"Og flush()-metoden er som å ta ut søppelet med en gang. Du kan bruke den før gjestene kommer."