• ne anlatıyorsunuz lan değişikler.
  • oop olmayan pythonic implementasyonu function decorator olan tasarım desendir.
  • mevcud bir class a farklı özellik eklemek için kullanılan patterndir. adapter ile çok karıştırılır. bu patternde mevcud class kapsüle edilmez. mevcud class dış dünyadan gizlenmez. en temel kullanımı mevcud classtan türetilen yeni bir decorator classı oluşturularak yapılır.
    adapter ya da proxy de esas oğlan classın instance ı adapter ya da proxy class ı içinde gizlenir dış dünyadan görülmez.

    edit : imla
  • design patterns in abap objects adlı kitapta sap abap uygulaması öğrenilebilecek pattern.

    özetle; birden fazla şekilde müdahale edilmesi gereken bir değişkenimiz var diyelim. müdahale edecek sınıfları zincir gibi uç uca dizip, değişeni her birine ayrı ayrı gönderiyoruz. hepsinden geçtiğinde, değişken son değerini / halini almış oluyor. tabii değişken yerine bir nesne de gönderilebilir.

    bunun tipik bir örneği, online pizza mağazasıdır. ziyaretçi pizzaya malzeme ekledikçe, pizza görselini malzeme sınıflarından geçire geçire üzerine eklenen malzemelerin görsellerini ilave ederiz.
  • bu tasarım kalıbının neden kullanıldığına ilişkin sıklıkla yapılan hata, sanki mevcut sınıfın üye fonksiyonuna* yalnızca yeni bir özellik eklemek olduğu yanılgısıdır. eğer amaç sadece bu olsaydı, statik zamanda mevcut sınıftan başka bir sınıf türetilerek ve ilgili method override edilerek de gerçeklenebilirdi.

    decorator pattern'in esas kullanım mantığı, bir sınıf nesnesine çalışma zamanında dinamik olarak sorumluluk* ekleyebilmektir. bunu sağlayabilmek için de ilgili sınıf en içte kalacak biçimde, yeni sorumlulukları temsil eden sınıf nesnelerinin üst üste katmanlar biçiminde bu sınıf nesnesini sarmasıdır. nitekim, decorator pattern'in bir diğer adı da wrapper'dır. sarmalanan sınıf nesnesi, karakteristik davranışından herhangi bir şey kaybetmez. en dıştaki katmana gelen bir mesaj, katmanlar arasında iletilerek en içteki nesneye yani dekore edilmek istenen sınıf nesnesine kadar ulaştırılır. bu sayede her katman kendine gelen isteği bir sonraki katmana iletirken, ek olarak kendi sorumluluğunu da gerçekleştirmiş olur. ve bütün bunlar çalışma zamanında dinamik olarak gerçekleştirilir (bunu bazı programlama dillerinde statik zamanda yapmanın yolları da mevcuttur). ayrıca dekoratör tasarım kalıbı bariz bir biçimde yapısaldır *, sorumluluk sahibidir ve rengârenktir.

    (bkz: dekorasyon günahları)
  • abap diliyle uygulanmış bir örnek, detaylı açıklamasıyla birlikte https://peloton4.com/…/27/decorator-design-pattern/ adresinde görülebilir.
  • bu pattern ile ilgili yanlis kani genellikle bir class a yeni bir ozellik eklemeye yaradigini dusunmektir. decorator pattern aslinda hali hazirda yaratilmis bir objenin bir fonksiyonunun islevini genisletmek icin vardir. ornekle gidelim.

    dusunun ki bir oyun programliyorsunuz ve bu oyunda karakterinizin bir tufegi var. ancak kullanici hali hazirda oyun oynarken ve tufegi varken siz var olan tufege susturucu, durbun gibi ozellikler eklemek istiyorsunuz(counter oynayanlar 4-3 e oyun aninda susturucu takmak olarak dusunebilir).

    tufeginizin fonksiyonu fire() olsun.

    tufegin butun aparatlarini bir member olarak tutmaya kalkarsak fire() fonkiyonunu her cagirdigimizda if(this.telescope!= null) if(silencer!=null) seklinde ates etmeden once aparatlar var mi yok mu kontrol edip ona gore atis karakteri olustururuz. yandi gulum keten helva. tufege eklenecek her ozellik yeni bir if demek.

    peki ya bu tufek ozellikleri miras alsa ? yine olmadi zira bu sefer programimizda

    riffle,
    riffle_with_telescop,
    riffle_with_silencer
    riffle_with_telescope_silencer

    isminde class larimiz olacak. hadi bir de kabza sokulup takiliyor olsun ? kac class olacak sen hesap et. bir de surekli runtime da mevcut tufegin state ini tutup yeni tufek yarattigimizda bu state i transfer etmekle ugrasicaz.

    ıste decorator pattern burada devreye girer. tufek objesini bir kere yaratiriz ve fire() fonksiyonu dumduz ates etmeye yarar. oyuncu oyunda iken tufege her aparat eklediginde bu fire fonksiyonunun islevini genisletiriz. peki nasil ? ahanda soyle:

    once tufegimiz icin bir interface tanimlariz. bu interface "iriffle" olsun ve fonksiyonu en basta belirttigimiz gibi fire() olsun

    class iriffle
    {
    public:
    virtual std::string fire() = 0;
    };

    class riffle : public iriffle
    {
    public:
    std::string fire() override
    {
    return "fire ";
    }
    };

    dumduz ates eden tufek tamam. simdi geldi tufegi dekore etmeye. bunun icin riffle_decorator diye bir abstract class tanimlariz ve bu class da iriffle interface inden turer ancak bir fark olarak iriffle turunden bir member tutar.

    class iriffle_decorator : public iriffle
    {
    protected:
    std::unique_ptr<iriffle> m_gun;
    public:
    virtual std::string fire() = 0;
    };

    ekleyecegimiz her ozellik artik tufegin fire() fonksyiyonuna ek bir is yapip bir ustundeki class in fire fonkiyonunu cagirir taaaa ki tufegin ana fire fonksiyonu cagirilana kadar.

    class telescope: public iriffle_decorator
    {
    public:
    telescope(std::unique_ptr< iriffle> telescopegun)
    {
    m_gun = std::move(telescopegun);
    }

    std::string fire() override
    {
    return m_gun->fire() + " with telescope";
    }
    };

    bak burasi onemli. telescopegun yaratirken bir tufek veriyoruz. fire dedigimizde once o verdigimiz tufegin fire fonksiyonunu ustune yapmak istedigimiz isi ekliyoruz.

    telescope da aslinda iriffle turunden bir obje oldugu icin ust uste dekore edip yeni bir ozellik ekleyebiliriz. susturucu ekleyelim

    class silencer : public riffle_decorator
    {
    public:
    silencer(std::unique_ptr<iriffle> guntodecorate)
    {
    m_gun = std::move(guntodecorate);
    }

    std::string fire() override
    {
    return (m_gun->fire()) + " with silencer";
    }
    };

    ornek main fonksiyonu su sekilde olur:

    std::unique_ptr<iriffle> mygun = std::make_unique<riffle>();
    std::cout << mygun->fire() << std::endl;
    mygun = std::make_unique<silencer>(std::move(mygun));
    std::cout << mygun->fire() << std::endl;
    mygun = std::make_unique<telescop>(std::move(mygun));
    std::cout << mygun->fire() << std::endl;

    std::cout << "\ncreate a fancy gun\n" << std::endl;

    std::unique_ptr<iriffle> fancygun = std::make_unique<telescop (std::make_unique<silencer>(std::make_unique<riffle>()));
    std::cout << fancygun->fire() << std::endl;

    dipnot: is bu entry deki kodlari dogrudan sozluge yazdim. kopyala yapistir yapmak isterseniz noktali virgulune parantezine bir goz atin.
  • tanım : programlama dilleri arasında bilinen bir (bkz: design pattern) ' dir.

    ps : python üzerinde , decoratorlere bakıyorum ama anlamadıgım nokta şu :

    def outer(some_functions):
    def inner():
    print('before the decorator ')
    ret = some_functions()
    return ret +1
    return inner

    def foo():
    return 1

    decorated = outer(foo)
    decorated()

    buraya kadar okey , fakat outer fonksiyonu ile yaptığımız işi ,

    def sample(functions):
    ret = functions()
    return ret + 1

    bu kod parçası ile de yapabiliyoruz , neden iç içe fonksiyon tanımalama gereği duyduk ?

    p.s: eger fonksiyonun argumani yoksa ic ice fonksiyona gerek yok, fakat , ustte aldigiminiz fonksiyonun parametresi var ise , ic ice fonksiyon kullanmak zorundaymisiz.
  • adı wrapper pattern olsa da olurdu. bir sınıfı başka bir sınıfın içerisine yerleştirerek onu dış dünyadan gizlemeye yarar. matruşka örneği verilebilir. runtime'da bir sınıfın davranışlarına müdahale ederken o sınıf üzerinde değişiklikler yapmamak için de ihtiyaç duyulur.

    decorator yapısal bir tasarım desenidir. en büyük avantajlarından bir sınıfın tek bir sorumluluğa sahip olmasına hizmet etmesidir. (bkz: single responsibility principle) mesela dev bir monolitik sınıf alt küçük decorator sınıflara dağıtılabilir. böylece yazılımın geri kalanı daha küçük sorumluluğa sahip bu küçük sınıfları kullanır. dünya daha güzel bir yer olur.

    sıkıntılı olduğu durumlar ise, bu wrapper sınıflar doğaları gereği doğal tasarım ağacının bir parçaları olmayabileceği için (daha sonradan ihtiyaçtan dolayı nesne ağacına eklendiklerinde) ilk başta işlevsel olsalar da zaman içinde yapılan eklemelerden dolayı şişebilirler ve nesne hiyeraşisini bozar hale gelebilirler. bu gidişat sezildiğinde erken önlem alınmalıdır.
hesabın var mı? giriş yap