"Kumusta, Amigo! Ngayon sasabihin ko sa iyo ang ilang mga kawili-wiling bagay tungkol sa klase ng BufferedInputStream, ngunit magsimula tayo sa « mga wrapper » at isang « bag ng asukal »."

"Ano ang ibig mong sabihin ng «pambalot» at «bag ng asukal»?"

"Ito ay mga metapora. Makinig. Kaya..."

Ang pattern ng disenyo ng «wrapper» (o «decorator») ay isang medyo simple at maginhawang mekanismo para sa pagpapalawak ng functionality ng object nang hindi gumagamit ng inheritance.

BufferedInputStream - 1

Ipagpalagay na mayroon kaming klase ng Cat na may dalawang pamamaraan: getName at setName:

Java code Paglalarawan
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;
 }
}
Ang klase ng Cat ay may dalawang paraan: getName at 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());
}
Isang halimbawa kung paano ito magagamit.

Ang "Oscar" ay ipapakita sa console.

Ipagpalagay na kailangan nating humarang ng isang method call sa isang bagay na pusa at marahil ay gumawa ng ilang maliliit na pagbabago. Para dito, kailangan nating balutin ito sa sarili nitong klase ng wrapper.

Kung gusto nating "i-wrap" ang sarili nating code sa mga tawag sa pamamaraan sa ilang bagay, kailangan nating:

1) Lumikha ng aming sariling klase ng wrapper at magmana mula sa parehong klase/interface bilang bagay na ibalot.

2) Ipasa ang bagay na ibalot sa constructor ng aming klase.

3) I-override ang lahat ng pamamaraan sa aming bagong klase. Gawin ang mga pamamaraan ng nakabalot na bagay sa loob ng bawat isa sa mga na-override na pamamaraan.

4) Gumawa ng anumang mga pagbabago na gusto mo: baguhin kung ano ang ginagawa ng mga tawag sa pamamaraan, baguhin ang kanilang mga parameter, at/o gumawa ng iba pa.

Sa halimbawa sa ibaba, hinarang namin ang mga tawag sa getName method ng isang object ng Cat at bahagyang binabago ang return value nito.

Java code Paglalarawan
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;
 }
}
Ang klase ng Cat ay naglalaman ng dalawang paraan: getName at 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);
 }
}
Ang klase ng wrapper. Ang klase ay hindi nag-iimbak ng anumang data maliban sa isang sanggunian sa orihinal na bagay.
Nagagawa ng klase na "magtapon" ng mga tawag sa orihinal na bagay (setName) na ipinasa sa constructor. Maaari din nitong "mahuli" ang mga tawag na ito at baguhin ang kanilang mga parameter at/o mga resulta .
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());
}
Isang halimbawa kung paano ito magagamit.

"Isang pusa na pinangalanang Oscar".
ay ipapakita sa console

Sa madaling salita, tahimik naming pinapalitan ang bawat orihinal na bagay ng isang bagay na pambalot, na tumatanggap ng isang link sa orihinal na bagay. Ang lahat ng mga tawag sa pamamaraan sa wrapper ay ipinapasa sa orihinal na bagay, at lahat ay tumatakbo tulad ng orasan.

"Gusto ko. Simple at functional ang solusyon."

"Sasabihin ko rin sa iyo ang tungkol sa isang «bag ng asukal». Ito ay isang metapora sa halip na isang pattern ng disenyo. Isang metapora para sa salitang buffer at buffering. Ano ang buffering at bakit natin ito kailangan?"

BufferedInputStream - 2

Sabihin natin na ngayon ay si Rishi na ang magluto, at tinutulungan mo siya. Wala pa si Rishi, pero gusto kong uminom ng tsaa. Hinihiling kong dalhan mo ako ng isang kutsarang asukal. Pumunta ka sa basement at humanap ng isang bag ng asukal. Maaari mong dalhin sa akin ang buong bag, ngunit hindi ko kailangan ang bag. Isang kutsara lang ang kailangan ko. Pagkatapos, tulad ng isang mahusay na robot, kumuha ka ng isang kutsara at dalhin ito sa akin. Idinagdag ko ito sa tsaa, ngunit hindi pa rin ito sapat na matamis. At hinihiling ko sa iyo na dalhan mo ako ng isa pa. Pumunta ka ulit sa basement at magdala ng isa pang kutsara. Pagkatapos ay sumama si Ellie, at hinihiling kong magdala ka ng asukal para sa kanya... Ang lahat ng ito ay masyadong mahaba at hindi epektibo.

Dumating si Rishi, nakita ang lahat ng ito, at hiniling sa iyo na dalhin siya ng isang mangkok ng asukal na puno ng asukal. Pagkatapos ay nagsimula na kaming humingi ni Ellie kay Rishi ng asukal. Inihain niya lang ito sa amin mula sa mangkok ng asukal, at iyon lang.

Ang nangyari pagkatapos lumitaw si Rishi ay tinatawag na buffering : ang sugar bowl ay isang buffer. Salamat sa buffering, maaaring basahin ng "mga kliyente" ang data mula sa isang buffer sa maliliit na bahagi , habang ang buffer, upang makatipid ng oras at pagsisikap, ay binabasa ang mga ito mula sa pinagmulan sa malalaking bahagi .

"Iyan ay isang cool na halimbawa, Kim. Naiintindihan ko nang lubos. Ang kahilingan para sa isang kutsarang asukal ay tulad ng pagbabasa ng isang byte mula sa isang stream."

"Eksakto. Ang klase ng BufferedInputStream ay isang klasikal na halimbawa ng isang buffered wrapper. Binabalot nito ang klase ng InputStream. Binabasa nito ang data mula sa orihinal na InputStream sa malalaking bloke sa isang buffer, at pagkatapos ay hinihila ito palabas ng buffer nang paisa-isa habang kami basahin mo mula rito."

"Very good. It's all clear. May buffers ba sa pagsusulat?"

"Oh, sige."

"Baka isang halimbawa?"

"Imagine a trash can. Imbes na lumabas para maglagay ng basura sa incinerator every time, itatapon mo na lang sa trash can. Tapos dadalhin ni Bubba ang lata sa labas minsan kada dalawang linggo. Isang classic na buffer."

"Nakakainteres! At mas malinaw kaysa sa isang bag ng asukal, nga pala."

"At ang flush() method ay parang pagtatapon kaagad ng basura. Magagamit mo ito bago dumating ang mga bisita."