Zaten var olan bir nesneye işlevselliği nasıl eklemeliyim?


25

Belirli miktarda iyi tanımlanmış işlevselliğe sahip bir arabirim var. Diyelimki:

interface BakeryInterface {
  public function createCookies();
  public function createIceCream();
}

Bu, arabirimin çoğu uygulaması için işe yarar, ancak birkaç durumda bazı yeni işlevler eklemeliyim (belki de yeni bir yönteme eklenmiş gibi createBrownies()). Bunu yapmak için aşikar / saf yaklaşım, arayüzü genişletmek olacaktır:

interface BrownieBakeryInterface extends BakeryInterface {
  public function createBrownies();
}

Ancak, mevcut API'yi değiştirmeden yeni işlevleri ekleyememem konusunda oldukça büyük bir dezavantaj var (yeni arayüzü kullanmak için sınıfı değiştirmek gibi).

Örneklemeden sonra işlevselliği eklemek için bir adaptör kullanmayı düşünüyordum :

class BrownieAdapter {
  private brownieBakery;

  public function construct(BakeryInterface bakery) {
    this->brownieBakery = bakery;
  }

  public function createBrownies() {
    /* ... */
  }
}

Hangi bana bir şey net olurdu:

bakery = new Bakery();
bakery = new BrownieBakery(bakery);
bakery->createBrownies();

Bu, soruna iyi bir çözüm gibi gözüküyor, ancak bunu yaparak eski tanrıları uyandırıp uyandırmadığımı merak ediyorum. Adaptör gitme yolu mu? İzlenecek daha iyi bir model var mı? Yoksa gerçekten sadece mermiyi ısırıyor ve orijinal arayüzü genişletiyor muyum?


Delphi'nin yardımcı sınıfları var, bu onları gerçekten değiştirmeden var olan sınıflara yöntem eklemek gibi. Örneğin Delphi'nin grafik ünitesinde tanımlanmış bir TBitmap sınıfı vardır, TBitmap'a bir Flip işlevi ekleyen bir yardımcı sınıf oluşturabilirsiniz. Yardımcı sınıf kapsamda olduğu sürece MyBitmap.Flip;
Bill

Yanıtlar:


14

Tutamak Gövdesi desenlerinden herhangi biri tam gereksinimlerinize, dile ve gereken soyutlama düzeyinize bağlı olarak açıklamaya uygun olabilir.

Saf yaklaşım , tam olarak aradığınızı yapan, nesnelere dinamik olarak sorumluluk ekleyen Dekoratör modeli olacaktır . Aslında fırın yapıyorsanız, kesinlikle overkill olur ve sadece Adapter ile gitmelisiniz.


Bu tam ihtiyacım olan şeydi: Bir adaptör kullanmanın bağımlılık enjeksiyonuyla vidalanacağını fark ettim, ancak bir dekoratör kullanmak bunun etrafında olur.

5

Özellikler , hala deneysel ancak zaten üretime dayanıklı Açı Yönelimli Programlama ve bazen nefret edilen Mixins gibi şeyleri bulabileceğiniz yatay yeniden kullanım kavramını araştırın .

Bir sınıfa yöntem eklemenin doğrudan bir yolu da programlama diline bağlıdır. Ruby, maymun eklemeye izin verirken, Javascript’in prototip tabanlı kalıtım, sınıfların gerçekte varolmadığı yerlerde, bir nesne yaratır ve sadece kopyalar ve eklemeye devam eder, örneğin:

var MyClass = {
    do : function(){...}
};

var MyNewClass = new MyClass;
MyClass.undo = function(){...};


var my_new_object = new MyNewClass;
my_new_object.do();
my_new_object.undo();

Son olarak, yatay yeniden kullanım ya da yansıtma ile sınıf / nesne davranışının "değişiklik" ve "ekleme" çalışma zamanlarını da taklit edebilirsiniz .


4

Bu bakeryörneğin davranışını dinamik olarak değiştirmesi gerektiğinde (kullanıcı işlemlerine bağlı olarak vb.) Bir gereklilik varsa , Dekoratör paternine gitmelisiniz .

Eğer bakeryonun davranış dinamik olarak değişmediğini ancak değiştiremez Bakery class(vb harici API) o zaman için gitmeli Adaptör deseni .

Eğer bakerydinamik davranışını değiştirmez ve değiştirebilirsiniz Bakery class(başlangıçta önerilen gibi) o zaman var olan arayüz uzanmalıdır veya tanıtmak yeni arayüzü BrownieInterface ve let Bakeryiki arabirimlerini BakeryInterfaceve BrownieInterface.
Aksi halde, kodunuza gereksiz bir karmaşıklık ekleyeceksiniz (Dekoratör kalıbını kullanarak).


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.