Kodun Dilinden Masallar: Adapter Pattern ile Farklı Dünyaları Birleştirmek

[en] Read in English

2023-06-15

Bir zamanlar, iki farklı dünyadan gelen iki arkadaş vardı: Elektrikli Süpürge ve Elektrik Prizi. Elektrikli Süpürge, enerjiye ihtiyaç duyuyordu ve bu enerjiyi Elektrik Prizinden almak istiyordu. Ancak bir sorun vardı. Elektrikli Süpürge’nin fişi, Elektrik Prizi’ne uymuyordu. İkisi de farklı standartlarda üretilmişti ve birbiriyle doğrudan iletişim kuramıyorlardı.

Bu durumda, bir kahraman ortaya çıktı: Adaptör. Adaptör, Elektrikli Süpürge’nin fişi ile Elektrik Prizi arasında bir köprü oluşturdu. Elektrikli Süpürge’nin fişini Adaptör’ün bir tarafına takıldı ve Adaptör’ün diğer tarafı Elektrik Prizi’ne takıldı. Böylece, Elektrikli Süpürge enerjiye kavuştu ve işlevini yerine getirebildi.

Bu masal, Adapter Pattern’ın temel mantığını anlatıyor. Adapter Pattern, birbirleriyle doğrudan iletişim kuramayan iki sınıf veya arayüz arasında bir köprü oluşturur. Bu sayede, bir sınıfın arayüzünü başka bir sınıfın beklediği arayüz şekline dönüştürür.

Adapter Pattern Diagram

Diagramda gördüğünüz gibi, Target sınıfı Adapter sınıfı tarafından kullanılıyor. Adapter sınıfı, Adaptee sınıfının specificRequest metodunu Target sınıfının anlayabileceği bir request metoduna dönüştürüyor.

Aşağıda Adapter Pattern’ın C#, Java, Go ve Rust dillerinde örneklerini bulabilirsiniz.

C#

// Target
public interface ITarget
{
    string Request();
}

// Adaptee
public class Adaptee
{
    public string SpecificRequest()
    {
        return "Specific Request";
    }
}

// Adapter
public class Adapter : ITarget
{
    private readonly Adaptee _adaptee;

    public Adapter(Adaptee adaptee)
    {
        _adaptee = adaptee;
    }

    public string Request()
    {
        return _adaptee.SpecificRequest();
    }
}

Java

// Target
public interface Target {
    String request();
}

// Adaptee
public class Adaptee {
    public String specificRequest() {
        return "Specific Request";
    }
}

// Adapter
public class Adapter implements Target {
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    public String request() {
        return adaptee.specificRequest();
    }
}

Go

// Target
type Target interface {
	Request() string
}

// Adaptee
type Adaptee struct{}

func (a *Adaptee) SpecificRequest() string {
	return "Specific Request"
}

// Adapter
type Adapter struct {
	Adaptee *Adaptee
}

func (a *Adapter) Request() string {
	return a.Adaptee.SpecificRequest()
}

Rust

// Target
pub trait Target {
    fn request(&self) -> &'static str;
}

// Adaptee
pub struct Adaptee;

impl Adaptee {
    pub fn specific_request(&self) -> &'static str {
        "Specific Request"
    }
}

// Adapter
pub struct Adapter {
    adaptee: Adaptee,
}

impl Target for Adapter {
    fn request(&self) -> &'static str {
        self.adaptee.specific_request()
    }
}

Bu örneklerde, Adapter sınıfı veya struct’ı, Adaptee sınıfının veya struct’ın specificRequest metodunu Target interface’inin veya trait’inin request metoduna dönüştürüyor. Bu sayede, Target interface’ini veya trait’ini kullanan kodlar, Adaptee sınıfının veya struct’ının özelliklerini Adapter aracılığıyla kullanabiliyor.

Adapter Pattern’ın bu dört dildeki örneklerini incelediğimizde, her dilin kendi özelliklerine göre farklı bir yaklaşım sergilediğini görebiliriz. Ancak temel prensip aynıdır: bir sınıf veya yapı (Adaptee), başka bir sınıf veya yapı (Target) tarafından kullanılabilir hale getirilir.

Bu örneklerde, Adapter sınıfı veya yapı, Adaptee sınıfının veya yapının specificRequest metodunu Target interface’inin veya trait’inin request metoduna dönüştürüyor. Bu sayede, Target interface’ini veya trait’ini kullanan kodlar, Adaptee sınıfının veya yapının özelliklerini Adapter aracılığıyla kullanabiliyor.

Adapter Pattern, iki sınıf veya yapı arasında uyumluluk sağlar ve böylece bir sınıfın veya yapının başka bir sınıfın veya yapının beklediği arayüz şekline dönüştürülmesini sağlar. Bu, kodun yeniden kullanılabilirliğini artırır ve daha esnek bir tasarım sağlar.

Bu örnekler, Adapter Pattern’ın farklı programlama dillerinde nasıl uygulanabileceğini göstermektedir. Her dilin kendi özelliklerine ve sözdizimine sahip olduğunu unutmayın, bu yüzden her dildeki uygulama biraz farklı olabilir. Ancak, Adapter Pattern’ın temel prensipleri her dilde aynıdır.



Bu gibi daha fazla gönderi...

Bileşenlerin Dansı: Composite Tasarım Kalıbı

2023-06-22 | #composite-pattern #design-patterns #structural-patterns

Bir zamanlar, bir ormanda bir ağaç vardı. Bu ağaç, yaprakları ve dalları olan karmaşık bir yapıydı. Her dalın üzerinde daha küçük dallar ve yapraklar bulunabilirdi. Ağaç, dallarını ve yapraklarını bir arada tutan bir bütün olarak çalışıyordu. Bu ağaç, Composite tasarım kalıbının bir örneğidir. Ağaç (Composite), dallar (yine Composite) ve yapraklar (Leaf) olmak üzere iki tür bileşen içerir. Hem dallar hem de yapraklar, ağaç tarafından tanınan aynı arayüzü (Component) uygular. Bu sayede ağaç, dallarını ve yapraklarını aynı şekilde işleyebilir.

Devamı 


Köprüler Kurarak Esneklik Kazanın: Bridge Tasarım Kalıbı İle Çözümlemeler ve Dört Farklı Dilde Uygulamalar

2023-06-22 | #bridge-pattern #design-patterns #structural-patterns

Bir zamanlar, iki krallık varmış. Bu krallıklar birbirlerine çok yakın olmasına rağmen, aralarında geniş ve derin bir nehir bulunuyormuş. Bu nehir, krallıkların birbirleriyle etkileşim kurmasını zorlaştırıyormuş. Bu durumu çözmek için, her iki krallık da bir köprü inşa etmeye karar vermiş. Bu köprü, iki krallık arasında iletişimi sağlayan bir arayüz olmuş. Ancak, köprünün her iki tarafında farklı yapılar ve özellikler bulunuyormuş. Bir taraf taştan, diğer taraf ise ahşaptan yapılmış. Bu durum, köprünün her iki tarafının birbirinden bağımsız olarak değiştirilebilmesini sağlamış.

Devamı 


Dekoratör Tasarım Deseni: Yazılımın Süsleyicileri

2023-06-15 | #decorator-pattern #design-patterns #structural-patterns

Bir zamanlar, bir “Component” adında bir nesne varmış. Bu nesne, belirli bir işlevi yerine getirmek için kullanılırmış. Ancak, bazen bu işlevi genişletmek veya değiştirmek gerekiyormuş. İşte bu noktada “Decorator"lar devreye giriyormuş. Decorator’lar, Component’i “süsleyen” veya genişleten nesnelerdir. Bir Decorator, bir Component’in üzerine gelir ve onun işlevini genişletir veya değiştirir. Bu, Component’in kendisini değiştirmeden, onun işlevselliğini genişletmek için kullanılır. Örneğin, bir “TextComponent” düşünün. Bu component, bir metni ekrana yazdırır. Ancak, bazen metni kalın veya italik yapmak isteyebiliriz.

Devamı 