Suunnittelupatteri : Decorator

Suunnittelupatteri Decorator eli 'koristelu' tai 'taggailu' on eräs varsin käytetty patteri nykyaikaisessa ohjelmistokehityksessä. Decoratorin ajatuksena on kutsua metoodia tai funktiota toisen funtion kautta. Perusajatusta voi kuvata muutamalla esimerkillä, python ja c# maailmassa.

Decorator käytössä

   class Decorator:
    def __init__(self):
     self.transaction = False


    def DecorateThis(self, delegate):
        self.StartTransaction()
        delegate()
        self.CloseTransaction()


    def StartTransaction(self):
        self.transaction = True
        print("Käynnistän transactionin")


    def CloseTransaction(self):
        self.transaction = False
        print("Sammuntan transactionin")

def DoSomething():
    print("Teen jotain")


decorator = Decorator()

decorator.DecorateThis(DoSomething)

C# kirjoitettuna tämä näyttäisi tältä.

using System;

namespace testailua
{
   public class Decorator
   {
        private bool _transactionIsOn = false;

         public void DecorateThis(Action action)
         {
            StartTransaction();
            action();
            CloseTransaction();
         }

        private void StartTransaction()
        {
            _transactionIsOn = true;
            Console.WriteLine("Käynnistän transactionin");
        }

        public void CloseTransaction()
        {
            _transactionIsOn = false;
            Console.WriteLine("Sammuntan transactionin");
        }
   }
    class Program
    {
        public static void Main(string[] args)
        {
             var decorate = new Decorator();
             decorate.DecorateThis(()=> Console.WriteLine("Teen jotain"));
        }
    }
}

Decorator tagina

Esimerkeissä näytetään miten decoratoria voi käyttää käynnistämään transaction käsittelyä. Tämä ei tietenkään ole se paras tapa käyttää decoratoria, mutta kuvaa miten suunnittelupatteri periaatteessa toimii.

Python puolella on mahdollista kutsua tagien kautta funktioita, mitä C#:ssa ei voi tehdä. Näin saadaan todellinen decoratio päälle. Edellinen esimerkki pythonin decorator patterin kautta laitettuna.

def Decorator(delegate):

    def StartTransaction():
        print("Käynnistän transactionin")


    def CloseTransaction():
        print("Sammuntan transactionin")

    StartTransaction()
    delegate()
    CloseTransaction()

@Decorator
def DoSomething():
    print("Teen jotain")
    return 0

try:
    DoSomething()
except:
    pass

C# puolella edellistä ei saa aikaan, koska Attributit ovat ainoastaan metadataa varten. Mikäli haluaa käyttää attribuutteja laukaisemaan funktioita pitää itse kirjoitaa laukaistavan koodin ympärille ensimmäisen esimerkin mukaan decoratori, joka etsii attribuutit koodista ja laukaisee tarvittaessa funktiot kirjoitettujen metadata ohjeiden mukaan. Eli käytännössä koko sovellus pitää laittaa ensin decoratori luokan rajapinnan läpi, joka sitten huolehtii sovelluksen metodien kutsuista.

Jos tunnet Asp.net corea, niin ymmärrät tätä asiaa, kun mietit miten controllerit ja filtterit suhtautuvat toisiinsa.

C# puolella tätä voisi tavallaan kutsua puutteeksi, sillä decoratorilla voi saada aikaan tehokkaita sovellus cacheita. Sovelluksen parametrien avulla voidaan decoraattorissa päätellä kannattaako tietokantaan mennä, vai palautetaanko vain edellisellä kerralla samoilla parametreillä tietokannasta saatuja arvoja.

Decoratori on tehokas tapa vähentää koodia. Toivottavasti tämän suunnittelupatterin tehokkuus avautui juuri sinulle.