Site icon Kerteriz Blog

Abstract Factory – Soyut Fabrika Tasarım Deseni

Abstract Factory - Soyut Fabrika Tasarım Deseni

Abstract Factory - Soyut Fabrika Tasarım Deseni

Abstract Factory (Soyut Fabrika) tasarım deseni, concreteabstract olmayan sınıfları tanımlamada kullanılan terim sınıfları belirlemeden ilgili nesnelerin ailelerini üretmenizi sağlayan creational kategorisindeki bir tasarım desenidir.

Daha önceki Tasarım Deseni / Kalıbı / Örüntüsü (Design Pattern) Nedir? başlıklı yazımızda tanıttığımız Creational Patterns altında yer alan Abstract Factory Method Nedir sorusunu ve kod örneklerini bu yazımızda oldukça detaylı paylaşıyoruz.

Bir mobilya mağazası simülatörü oluşturduğunuzu hayal edin. Kodunuz aşağıdakileri temsil eden sınıflardan oluşur:

Ürün aileleri ve çeşitleri.

Aynı aileden diğer nesnelerle eşleşmeleri için bireysel mobilya nesneleri oluşturmanın bir yoluna ihtiyacınız var. Müşteriler, eşleşmeyen mobilyalar aldıklarında oldukça sinirleniyorlar.

Modern tarzdaki bir kanepe, Viktorya tarzı sandalyelerle eşleşmez.

Ayrıca, programa yeni ürünler veya ürün aileleri eklerken mevcut kodu değiştirmek istemezsiniz. Mobilya satıcıları kataloglarını çok sık günceller ve her seferinde temel kodu değiştirmek istemezsiniz.

Çözüm

Soyut Fabrika modelinin önerdiği ilk şey, ürün ailesinin her bir farklı ürünü için (örneğin, sandalye, kanepe veya sehpa) interfaceleri açıkça bildirmektir. Ardından tüm ürün çeşitlerinin bu interfaceleri takip etmesini sağlayabilirsiniz. Örneğin, tüm koltuk çeşitleri, Koltuk interface’ini uygulayabilir; tüm sehpa çeşitleri, CoffeeTable interface’ini vb. uygulayabilir.

Aynı nesnenin tüm varyantları tek bir sınıf hiyerarşisine taşınmalıdır.

Bir sonraki adım, ürün ailesinin parçası olan tüm ürünler için (örneğin, createChair, createSofa ve createCoffeeTable) oluşturma yöntemlerinin bir listesini içeren bir interface olan Soyut Fabrika‘yı tanımlamaktır. Bu yöntemler, daha önce çıkardığımız interfaceler tarafından temsil edilen soyut ürün türlerini döndürmelidir: Sandalye, Kanepe, Kahve Masası vb.

Her concrete factory belirli bir ürün çeşidine karşılık gelir.

Peki ya ürün çeşitleri? Bir ürün ailesinin her bir çeşidi için AbstractFactory interface’ine dayalı ayrı bir factory sınıfı oluşturuyoruz. Bir factory, belirli bir türden ürünleri döndüren bir sınıftır. Örneğin, ModernFurnitureFactory yalnızca ModernChair, ModernSofa ve ModernCoffeeTable nesneleri oluşturabilir.

İstemci kodu, ilgili soyut interfaceler aracılığıyla hem fabrikalar hem de ürünlerle çalışmak zorundadır. Bu, müşteri koduna ilettiğiniz bir fabrikanın türünü ve ayrıca müşteri kodunun aldığı ürün çeşidini gerçek müşteri kodunu bozmadan değiştirmenize olanak tanır.

Müşteri, birlikte çalıştığı fabrikanın concrete sınıfıyla ilgilenmemelidir.

Müşterinin sandalye üretmek için bir factory istediğini varsayalım. Müşteri, fabrikanın sınıfının farkında olmak zorunda değildir ve ne tür bir sandalye aldığı önemli değildir. İster Modern bir model ister Victoria tarzı bir sandalye olsun, müşteri soyut Sandalye interface’ini kullanarak tüm sandalyelere aynı şekilde davranmalıdır. Bu yaklaşımla müşterinin sandalye hakkında bildiği tek şey, sitOn yöntemini bir şekilde uyguladığıdır. Ayrıca, sandalyenin hangi çeşidi return edilirse edilsin, her zaman aynı fabrika nesnesi tarafından üretilen kanepe veya sehpa tipiyle eşleşecektir.

Açıklığa kavuşturulması gereken bir şey daha var:. Müşteri yalnızca soyut interfacelere maruz kalıyorsa, gerçek factory nesnelerini ne yaratır? Genellikle uygulama, initialitization aşamasında concrete bir factory nesnesi oluşturur. Bundan hemen önce uygulama, yapılandırmaya veya ortam ayarlarına bağlı olarak fabrika türünü seçmelidir.

Structure

  1. Abstract products, bir ürün ailesini oluşturan bir dizi farklı ancak ilgili ürün için interfaceler bildirir.
  2. Concrete products, varyantlara göre gruplandırılmış abstract ürünlerin çeşitli implementasyonlarıdır. Her abstract ürün (sandalye/kanepe), verilen tüm varyantlarda (Victoria/Modern) uygulanmalıdır.
  3. Abstract Factory interface’i, abstract ürünlerin her birini oluşturmak için bir dizi yöntem bildirir.
  4. Concrete Fabrikalar, abstarct fabrikanın yaratma yöntemlerini uygular. Her concrete fabrika, belirli bir ürün çeşidine karşılık gelir ve sadece bu ürün çeşitlerini yaratır.
  5. Abstract fabrikalar concrete ürünleri örneklendirselerde, yaratma yöntemlerinin imzaları karşılık gelen abstract ürünleri döndürmelidir. Bu şekilde, bir fabrikayı kullanan müşteri kodu, bir fabrikadan aldığı ürünün belirli bir çeşidiyle eşleşmez. Müşteri herhangi bir concrete fabrika ile çalışma şansı yakalar.

# Abstract Factory Pseudocode

Bu örnek, oluşturulan tüm öğeleri seçili bir işletim sistemiyle tutarlı tutarken, istemci kodunu concrete UI sınıflarına bağlamadan platformlar arası UI öğeleri oluşturmak için Soyut Fabrika modelinin nasıl kullanılabileceğini gösterir.

Cross-platform UI sınıfları örneği.

Bir cross-platform uygulamadaki aynı UI öğelerinin benzer şekilde davranması beklenir, ancak farklı işletim sistemlerinde biraz farklı görünür. Ayrıca, UI öğelerinin mevcut işletim sisteminin stiliyle eşleştiğinden emin olmak sizin işiniz. Programınızın Windows’ta yürütüldüğünde macOS denetimlerini oluşturmasını istemezsiniz.

Abstract Factory interface, istemci kodunun farklı türde UI öğeleri üretmek için kullanabileceği bir dizi oluşturma yöntemi bildirir. Concrete fabrikalar, belirli işletim sistemlerine karşılık gelir ve söz konusu işletim sistemine uyan UI öğelerini oluşturur.

Şu şekilde çalışır: Bir uygulama başlatıldığında mevcut işletim sisteminin türünü kontrol eder. Uygulama, işletim sistemiyle eşleşen bir sınıftan bir fabrika nesnesi oluşturmak için bu bilgileri kullanır. Kodun geri kalanı, UI öğeleri oluşturmak için bu fabrikayı kullanır. Bu, yanlış öğelerin oluşturulmasını önler.

Bu yaklaşımla, istemci kodu, abstract interfaceler aracılığıyla bu nesnelerle çalıştığı sürece, concrete fabrika sınıflarına ve UI öğelerine bağlı değildir. Bu ayrıca, istemci kodunun gelecekte ekleyebileceğiniz diğer fabrikaları veya UI öğelerini desteklemesine de olanak tanır.

Sonuç olarak, uygulamanıza her yeni UI öğesi varyasyonu eklediğinizde istemci kodunu değiştirmeniz gerekmez. Bu öğeleri üreten yeni bir fabrika sınıfı oluşturmanız ve uygun olduğunda o sınıfı seçmesi için uygulamanın başlatma kodunu biraz değiştirmeniz yeterlidir.

// Soyut fabrika arabirimi, farklı soyut ürünler döndüren bir dizi method bildirir. 
// Bu ürünlere aile denir ve üst düzey bir tema veya konseptle ilişkilidir. 
// Bir ailenin ürünleri genellikle kendi aralarında işbirliği yapabilir. 
// Bir ürün ailesinin birkaç çeşidi olabilir, ancak bir çeşidin ürünleri 
// başka bir çeşidin ürünleri ile uyumlu değildir.
interface GUIFactory is
    method createButton():Button
    method createCheckbox():Checkbox

// Concrete fabrikalar, tek bir varyanta ait bir ürün ailesi üretir. 
// Fabrika, ortaya çıkan ürünlerin uyumlu olduğunu garanti eder. 
// Concrete fabrikanın yöntemlerinin imzaları abstract bir ürün döndürürken, 
// yöntemin içinde concrete bir ürün örneklendirilir.
class WinFactory implements GUIFactory is
    method createButton():Button is
        return new WinButton()
    method createCheckbox():Checkbox is
        return new WinCheckbox()

// Her concrete fabrikanın karşılık gelen bir ürün çeşidi vardır.
class MacFactory implements GUIFactory is
    method createButton():Button is
        return new MacButton()
    method createCheckbox():Checkbox is
        return new MacCheckbox()

// Bir ürün ailesinin her farklı ürününün bir temel interface'i olmalıdır. 
// Ürünün tüm çeşitleri bu interface'i uygulamalıdır.
interface Button is
    method paint()

// Concrete ürünler, ilgili concrete fabrikalar tarafından oluşturulur.
class WinButton implements Button is
    method paint() is
        // Render a button in Windows style.

class MacButton implements Button is
    method paint() is
        // Render a button in macOS style.

// İşte başka bir ürünün temel interface'i. 
// Tüm ürünler birbirleriyle etkileşime girebilir, 
// ancak uygun etkileşim yalnızca aynı concrete varyantın ürünleri arasında mümkündür.
interface Checkbox is
    method paint()

class WinCheckbox implements Checkbox is
    method paint() is
        // Render a checkbox in Windows style.

class MacCheckbox implements Checkbox is
    method paint() is
        // Render a checkbox in macOS style.

// İstemci kodu fabrikalar ve ürünlerle yalnızca soyut türler aracılığıyla çalışır: 
// GUIFactory, Button ve Checkbox. Bu, herhangi bir fabrika veya ürün alt sınıfını, 
// onu bozmadan müşteri koduna geçirmenizi sağlar.
class Application is
    private field factory: GUIFactory
    private field button: Button
    constructor Application(factory: GUIFactory) is
        this.factory = factory
    method createUI() is
        this.button = factory.createButton()
    method paint() is
        button.paint()

// Uygulama, mevcut konfigürasyona veya ortam ayarlarına bağlı olarak fabrika tipini seçer
// ve çalışma zamanında (genellikle başlatma aşamasında) oluşturur.
class ApplicationConfigurator is
    method main() is
        config = readApplicationConfigFile()

        if (config.OS == "Windows") then
            factory = new WinFactory()
        else if (config.OS == "Mac") then
            factory = new MacFactory()
        else
            throw new Exception("Error! Unknown operating system.")

        Application app = new Application(factory)

Uygulanabilirlik

Kodunuzun çeşitli ilgili ürün aileleriyle çalışması gerektiğinde, ancak bu ürünlerin concrete sınıflara bağlı olmasını istemiyorsanız, bunlar önceden bilinmiyor olabilir veya yalnızca gelecekteki genişletilebilirliğe izin vermek istediğinizde Soyut Fabrikayı kullanın.

Abstract Factory, ürün ailesinin her sınıfından nesneler oluşturmak için size bir interface sağlar. Kodunuz bu interface aracılığıyla nesneler oluşturduğu sürece, uygulamanız tarafından halihazırda oluşturulmuş ürünlerle eşleşmeyen bir ürünün yanlış varyantını oluşturma konusunda endişelenmenize gerek yoktur.

🗎 Nasıl Implemente Edeceğiz?

  1. Ürünlerin çeşitlerine karşı farklı ürün türlerinden oluşan bir matrisin haritasını çıkarın.
  2. Tüm ürün türleri için abstract ürün arayüzleri bildirin. Ardından, tüm concrete ürün sınıflarının bu interfaceleri uygulamasını sağlayın.
  3. Tüm abstract ürünler için bir dizi oluşturma yöntemiyle soyut fabrika interfaceini tanımlayın.
  4. Her ürün çeşidi için bir tane olmak üzere bir dizi concrete fabrika sınıfı implemente edin.
  5. Uygulamada bir yerde fabrika initialization kodu oluşturun. Uygulama yapılandırmasına veya mevcut ortama bağlı olarak, concrete fabrikası sınıflarından birini başlatması gerekir. Bu fabrika nesnesini, ürünleri oluşturan tüm sınıflara geçirin.
  6. Kodu tarayın ve ürün constructorlarına yapılan tüm doğrudan erişimleri bulun. Bunları fabrika nesnesindeki uygun oluşturma yöntemine yapılan çağrılarla değiştirin.

Abstract Factory Method Avantajları ve Dezavantajları

⇄ Diğer Desenlerle İlişkisi

<> Kod Örneği

Abstract Factory Method Example

Aşağıdaki public repo adresine giderek adresine giderek örnek Abstract Factory method kodlarını inceleyebilirsiniz.

Github repoya gitmek için Tıklayınız.

Exit mobile version