Adapter Design Pattern

Bir sınıf değişime kapalı, gelişmeye açık olmalıdır. Eğer bir uygulama geliştirdikten sonra birkaç sınıfı değiştirirseniz, uygulamada o sınıfın kullanıldığı her yeri değiştirmeniz gerekecektir. Bu durum, küçük uygulamalarda çok büyük bir sorun gibi görünmese de, büyük uygulamalarda sorun olmaya başlayabilir.

Sınıfların fonksiyonalitesini değiştirmek için, sınıfı extends edip yeni bir sınıf oluşturup, yeni fonksiyonları oraya ekledikten sonra, istemci koda (client code) senin kullanacağın yeni sınıf budur diyebilirsiniz. Ama bu durumda da, istemci sürekli farklı sınıflar kullanmış olacaktır.

İstemci kodun, orjinal sınıfın değişikliklerinden en az şekilde etkilenmesi için, istemci kod ile sınıfların arasına bir katman koyulabilir. Bu kullanım, gerçek hattaki adaptör mantığına benzemektedir. Adaptör, cihaza uygun elektriği vererek bozulmamasını ve cihazın güç çekmesini sağlayacaktır.

Adapter design pattern, bir sınıfın fonksiyonalitesini değiştirmek istiyorsanız işinize yarayabilir. Yazacağınız bir adapter sınıfı, orjinal sınıfınıza adapte olarak ihtiyacınız olan yeni fonksiyonları eklemenizi sağlar.

PHP ile Adapter Design Pattern

Email gönderen bir uygulama yaptığımızı varsayın ve aşağıdaki şekilde bir Email sınıfı yazalım:

class Email
{
    public $text;
    public $from;
    public $to;
    public function __construct($text, $from, $to)
    {
        $this->text = $text;
        $this->from = $from;
        $this->to   = $to;
    }
    public function send()
    {
        echo "Email sent. <br>";
        echo "TEXT: $this->text <br>";
        echo "FROM: $this->from <br>";
        echo "TO: $this->to <br><br>";
    }
}

Bu sınıfı da şu şekilde kullanalım:

$email = new Email('Hi, whatsup ?', 'cdemir1991@gmail.com', 'stranger@stranger12.com');
$email->send();

Bu durumda Email sınıfında herhangi bir değişiklik olursa; mesela emaili kontrol eden bir fonksiyon eklenirse, sınıfı şu şekilde kullanmamız gerekecek:

$email = new Email('Hi, whatsup ?', 'cdemir1991@gmail.com', 'stranger@stranger12.com');
$email->validate();
$email->send();

Uygulamanın her yerinde validate fonksiyonu olmaksızın kullandığımız Email sınıfı bir anda validate fonksiyonu ile beraber kullanılmaya başlandı. Uygulamanın her yerinde değişiklik yapmamız gerekecek ya da araya bir adapter sınıfı koyarak, istemci kodun değişiklik yapmadan aynı şekilde Email sınıfını kullanmasını sağlayacağız.

Bir ileri seviye olarak, bu değişikliğin olabileceğini önceden planlayarak, istemci kodun direk Email sınıfına değil, adapter sınıfına istek yapmasını sağlamalıyız.

Adapter sınıfımız şu şekilde olsun:

class Send
{
    public static function email($text, $from, $to)
    {
        $email = new Email($text, $from, $to);
        if ($email->validate()) {
            $email->send();
        }
    }
}

İstemci kod ise Email göndermek için Adapter sınıfını kullansın:

Send::email('Hi, whatsup ?', 'cdemir1991@gmail.com', 'stranger@stranger.com');

Bundan sonra Email sınıfında oluşabilecek tüm değişiklikler için Adapter sınıfını (bir diğer deyişle Send sınıfını) değiştirmemiz yeterli olacaktır.

Adapter design pattern kısaca, kurduğunuz mimaridaki değişiklikleri kontrol etmenizi sağlar. Bir sınıfı, istemcinin beklediği şekle çevirir.

Yazının buraya kadar olan kısmında Adapter design patterin‘in ne oldğunu anlatmaya çalıştım. Devamında ise uygulamayı biraz daha geliştirmek istiyorum.

Bu uygulama şu an Email gönderiyor. Bizden SMS göndermesini de istediklerini varsayalım ve bir SMS sınıfı yazalım:

class SMS
{
    public $text;
    public $number;
    public function __construct($text, $number)
    {
        $this->text = $text;
        $this->number = $number;
    }
    public function validate()
    {
        // Check for 160 character
        return true;
    }
    public function send()
    {
        echo "SMS sent. <br>";
        echo "TEXT: $this->text <br>";
        echo "NUMBER: $this->number <br><br>";
    }
}

SMS göndermek için de direk SMS sınıfını değil, az önce oluşturduğumuz Adapter sınıfını kullanalım, yani Email ve SMS sınıflarının Adapter sınıfları ortak olsun:

class Send
{
    public static function email($text, $from, $to)
    {
        $email = new Email($text, $from, $to);
        if ($email->validate()) {
            $email->send();
        }
    }
    public static function sms($text, $target)
    {
        $sms = new SMS($text, $target);
        if ($sms->validate()) {
            $sms->send();
        }
    }
}

İstemci artık hem Email hem de SMS gönderebilir durumdadır:

Send::email('Hi, whatsup ?', 'cdemir1991@gmail.com', 'stranger@stranger.com');
Send::sms('Hey, how is going ?', '+905597778899');

Son olarak uygulamaya tweet gönderen bir sınıf ekleyelim:

class Twitter
{
    public $text;
    public $from;
    public function __construct($text, $from)
    {
        $this->text = $text;
        $this->from = $from;
    }
    public function validate()
    {
        // Check for 140 character
        return true;
    }
    public function connect()
    {
        // Connect to the twitter API
    }
    public function send()
    {
        echo "Tweet sent. <br>";
        echo "TWEET: $this->text <br>";
        echo "FROM: $this->from <br><br>";
    }
}

Twitter sınıfı için de Adapter mimarisini kullanalım:

class Send
{
    public static function email($text, $from, $to)
    {
        $email = new Email($text, $from, $to);
        if ($email->validate()) {
            $email->send();
        }
    }
    public static function sms($text, $target)
    {
        $sms = new SMS($text, $target);
        if ($sms->validate()) {
            $sms->send();
        }
    }
    public static function tweet($tweet, $from)
    {
        $tweet = new Twitter($tweet, $from);
        if ($tweet->validate()) {
            $tweet->connect();
            $tweet->send();
        }
    }
}

Artık uygulamamız hem Email, hem SMS hem de Tweet gönderebilir durumdadır. İstemci kod Adapter sınıfını kullanarak istediği şekilde gönderim yapabilir.

Send::email('Hi, whatsup ?', 'cdemir1991@gmail.com', 'stranger@stranger.com');
Send::sms('Hey, how is going ?', '+905597778899');
Send::tweet('Hello, twitter !', 'username');

Benim burada dikkat çekmek istediğim nokta, istemciye olabildiğince doğal dile yakın bir şekilde sınıfları ve fonksiyonları kullandırmaktır. Send email, send sms, send tweet gibi doğal dilde de gerçekten anlamı olan söz dizimleri kullanmak ve kullandırtmak, bence yazılan kodun kalitesinin belirlenmesinde bir etkendir.

Benzer Yazılar

Yorumlar

Yorum Yazın

Su elementleri kullanabilirsiniz : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Arama
RSS
Beni yukari isinla