"Merhaba, Amigo! Bugün size BufferedInputStream sınıfı hakkında birkaç ilginç şey anlatacağım, ama « sarmalayıcılar » ve bir « torba şeker » ile başlayalım .

"'Kağıtçı' ve 'şeker torbası' derken neyi kastediyorsunuz?"

"Bunlar metafor. Dinle. Yani..."

"Sarmalayıcı" (veya "dekoratör") tasarım modeli, nesne işlevselliğini kalıtım kullanmadan genişletmek için oldukça basit ve kullanışlı bir mekanizmadır.

BufferedInputStream - 1

Diyelim ki iki yöntemi olan bir Cat sınıfımız var: getName ve setName:

java kodu Tanım
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 sınıfının iki yöntemi vardır: getName ve 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());
}
Nasıl kullanılabileceğine dair bir örnek.

Konsolda «Oscar» görüntülenecektir.

Bir cat nesnesindeki bir yöntem çağrısını yakalamamız ve belki de bazı küçük değişiklikler yapmamız gerektiğini varsayalım. Bunun için onu kendi wrapper sınıfına sarmamız gerekiyor .

Kendi kodumuzu bir nesnedeki yöntem çağrılarının etrafına "sarmak" istiyorsak , şunları yapmalıyız:

1) Kendi sarmalayıcı sınıfımızı oluşturun ve sarılacak nesneyle aynı sınıftan/arayüzden miras alın.

2) Sarılacak nesneyi sınıfımızın yapıcısına iletin.

3) Yeni sınıfımızdaki tüm yöntemleri geçersiz kılın. Geçersiz kılınan yöntemlerin her birinin içinde sarılmış nesnenin yöntemlerini çağırın.

4) İstediğiniz değişiklikleri yapın: yöntem çağrılarının ne yaptığını değiştirin, parametrelerini değiştirin ve/veya başka bir şey yapın.

Aşağıdaki örnekte, bir Cat nesnesinin getName yöntemine yapılan çağrıları yakalıyoruz ve dönüş değerini biraz değiştiriyoruz.

java kodu Tanım
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 sınıfı iki yöntem içerir: getName ve 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);
 }
}
Sarmalayıcı sınıfı. Sınıf, orijinal nesneye bir referans dışında herhangi bir veri saklamaz.
Sınıf, yapıcıya iletilen orijinal nesneye (setName) çağrıları "atabilir". Ayrıca bu aramaları "yakalayabilir" ve parametrelerini ve/veya sonuçlarını değiştirebilir .
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());
}
Nasıl kullanılabileceğine dair bir örnek.

"Oscar adında bir kedi".
konsolda görüntülenecek

Başka bir deyişle, her orijinal nesneyi, orijinal nesneye bir bağlantı alan bir sarmalayıcı nesneyle sessizce değiştiririz. Sarmalayıcıdaki tüm yöntem çağrıları orijinal nesneye iletilir ve her şey saat gibi çalışır.

"Beğendim. Çözüm basit ve işlevsel."

"Ayrıca bir 'şeker torbası'ndan da bahsedeceğim. Bu bir tasarım modelinden ziyade bir metafor. Tampon ve tamponlama kelimelerinin metaforu. Tamponlama nedir ve buna neden ihtiyacımız var?"

BufferedInputStream - 2

Diyelim ki bugün yemek yapma sırası Rishi'de ve siz ona yardım ediyorsunuz. Rishi henüz burada değil ama ben çay içmek istiyorum. Bana bir kaşık şeker getirmeni rica ediyorum. Bodruma gidiyorsun ve bir torba şeker buluyorsun. Bana tüm çantayı getirebilirsin ama çantaya ihtiyacım yok. Sadece bir kaşığa ihtiyacım var. Sonra iyi bir robot gibi bir kaşık alıp bana getir. Çaya ekliyorum ama yine de yeterince tatlı değil. Ve senden bana bir tane daha getirmeni istiyorum. Tekrar bodruma gidersin ve bir kaşık daha getirirsin. Sonra Ellie geliyor ve senden ona şeker getirmeni istiyorum... Bütün bunlar çok uzun sürüyor ve verimsiz.

Rishi gelir, tüm bunları görür ve sizden ona şeker dolu bir şekerlik getirmenizi ister. Sonra Ellie ve ben Rishi'den şeker istemeye başladık. Bize sadece şekerlikten servis ediyor ve hepsi bu.

Rishi ortaya çıktıktan sonra olanlara tamponlama denir : şekerlik bir tampondur. Arabelleğe alma sayesinde, "istemciler" arabellekteki verileri küçük bölümler halinde okuyabilirken arabellek, zamandan ve emekten tasarruf etmek için bunları kaynaktan büyük bölümlerde okur .

"Bu harika bir örnek Kim. Çok iyi anlıyorum. Bir kaşık şeker istemek, bir akıştan bir bayt okumak gibidir."

"Kesinlikle. BufferedInputStream sınıfı, arabelleğe alınmış sarmalayıcının klasik bir örneğidir. InputStream sınıfını sarar. Büyük bloklar halinde orijinal InputStream'den gelen verileri bir arabelleğe okur ve sonra biz onu arabellekten parça parça çeker. ondan oku."

"Çok iyi. Her şey açık. Yazmak için arabellek var mı?"

"Tabiiki."

"Belki bir örnek?"

"Bir çöp tenekesi düşünün. Her seferinde çöpü yakma fırınına atmak için dışarı çıkmak yerine, onu çöp kutusuna atıyorsunuz. Sonra Bubba iki haftada bir tenekeyi dışarı çıkarıyor. Klasik bir tampon."

"Ne kadar ilginç! Bu arada, bir torba şekerden çok daha net."

"Veflush() yöntemi, çöpü hemen dışarı çıkarmak gibidir. Onu misafirler gelmeden önce kullanabilirsiniz."