Neden Soyut fabrika tasarım modeline ihtiyacımız var?


124

Tanımın çoğu şöyle diyor:

Soyut bir fabrika, somut sınıflarını belirtmeden ilgili nesnelerin ailelerini oluşturmak için bir arayüz sağlar.

Somut sınıfın kendisinin nesnesini yaratarak görevi başarabileceğimiz için Soyut Fabrika Modelinin kullanımı nedir? Neden Beton sınıfının nesnesini yaratan bir fabrika yöntemimiz var?

Lütfen bana abstractFactory modelini uygulamam gereken herhangi bir gerçek hayat örneği sağlayın?

Yanıtlar:


218

6
Tüm bu örnekler Fabrika Yöntemi Modelini açıklar çünkü hepsi tek bir ürün arabirimi döndürür. Bunların hiçbiri Soyut Fabrika Modeli değildir, çünkü hiçbiri ilgili ürün arayüzlerinden oluşan bir aile üretmez.
jaco0646

32
Eksiksiz açıklama amacıyla, bu cevabın yazarı, bağlantılı cevapların her birinin yazarı olduğunu da açıkça belirtmiş olmalıdır; bu nedenle bu liste SO topluluğundan temsili bir örnek DEĞİLDİR .
jaco0646

1
@ jaco0646 IIRC, Fabrika Yöntemi kalıbı , kalıtıma dayanan Şablon Yöntemi modelinin bir uzmanlığıdır . Ancak şu anda seyahat ettiğim ve GoF kitabım yanımda olmadığı için yanılıyor olabilirim. "Hiçbiri ilgili ürün arayüzleri ailesi üretmiyor" derken neyi kastediyorsunuz?
Mark Seemann

1
Bir fabrikanın Soyut Fabrika Modeline uymadığını gösteren en basit ipucu, fabrikanın ürettiği soyut ürünleri saymaktır ("soyut" kelimesinin aşırı kullanımını önlemek için "soyut ürünler" yerine "ürün arayüzleri" terimini kullandım) . Tek bir soyut ürün üreten bir fabrika Soyut Fabrika olamaz çünkü tanımı gereği Soyut Fabrika ilgili ürünlerden oluşan bir aile üretir . Bu ailenin bir arayüzün farklı uygulamalarına değil, farklı, ilgili arayüzlere sahip ürünlere atıfta bulunduğunu belirtmek önemlidir .
jaco0646

1
İşte bir örnek oodesign.com/abstract-factory-pattern.html . Soyut fabrika modelinin başlangıçta yaratıldığı şey budur.
user2802557

23

Abstract Factory modelinin kullanımına ilişkin gerçek hayattan bir örnek, iki farklı veri kaynağına veri erişimi sağlamaktır. Uygulamanızın farklı veri depolarını desteklediğini varsayın. (örneğin bir SQL Veritabanı ve bir XML dosyası). İki farklı veri erişim arabiriminiz var, örneğin bir IReadableStoreve IWritableStorekullanılan veri kaynağı türüne bakılmaksızın uygulamanızın beklediği ortak yöntemleri tanımlama.

Kullanılacak veri kaynağı türü, müşteri kodunun veri erişim sınıflarını alma şeklini değiştirmemelidir. Sizin AbstractDataAccessFactoryveri kaynağı türü yapılandırıldığı bilir ve bir sağlar beton Fabrikası istemci kodu için, yani SqlDataAccessFactoryya XmlDataAccessFactory. Bu beton fabrikalar somut uygulamaları oluşturabilir, örneğin SqlReadableStoreve SqlWriteableStore.

DbProviderFactory .NET Framework bu modelinin bir örneğidir.


18
Bu cevap, Fabrika Yöntemi modelini veya Statik Fabrika modelini doğru bir şekilde tanımlayabilir, ancak Soyut Fabrika modelini tanımlayamaz.
jaco0646

5

Sizi doğru anladıysam - soru şu ki, neden hem Fabrika yöntemine hem de soyut fabrika kalıplarına sahibiz? Farklı polimorfik sınıfların farklı örnekleme prosedürü olduğunda soyut fabrikaya ihtiyacınız vardır. Ve bazı modüllerin, nesne başlatmanın herhangi bir detayını bilmeden örnekler oluşturmasını ve bunları kullanmasını istiyorsunuz. Örneğin - bazı hesaplamalar yaparak Java nesneleri oluşturmak istiyorsunuz. Ancak bazıları uygulamanın bir parçasıyken, diğerlerinin bayt kodu DB'den okunmalıdır. Öte yandan - neden fabrika yöntemine ihtiyacımız var? Kabul ediyorum, bu soyut fabrika bununla örtüşüyor. Ancak bazı durumlarda - yazmak çok daha az koddur, daha az sınıfa ve arabirime sahip olmak, sistemin anlaşılmasını kolaylaştırır.


4

Somut sınıfın kendisinin nesnesini yaratarak görevi başarabileceğimiz için Soyut Fabrika Modelinin kullanımı nedir? Neden Beton sınıfının nesnesini yaratan bir fabrika yöntemimiz var?

Abstract Factory'nin yokluğunda , Müşterinin somut sınıfların ayrıntılarını bilmesi gerekir. Bu sıkı bağlantı Soyut Fabrika ile kaldırıldı .

Şimdi Fabrika Yöntemi , müşterinin kullanmak zorunda olduğu bir sözleşmeyi ortaya koyuyor. Fabrika Yöntemi ile gösterilen arayüzü uygulayan yeni ürünler ekleyerek fabrikanıza daha fazla ürün ekleyebilirsiniz.

Daha iyi anlamak için bu ilgili SE sorularına bakın:

Fabrika ve Soyut Fabrika Kalıpları arasındaki temel fark nedir?

niyet:

Somut sınıflarını belirtmeden ilgili veya bağımlı nesnelerin ailelerini oluşturmak için bir arayüz sağlayın.

Sen anlayabileceği Niyet, Yapısı, Kontrol Listesi ve başparmak kuralları arasında Özet Fabrika bundan desen sourcemaking makalesinde.

Kontrol Listesi:

  1. Platform bağımsızlığının ve oluşturma hizmetlerinin mevcut acı kaynağı olup olmadığına karar verin .
  2. Ürünlere karşı bir platform matrisi oluşturun .
  3. Her ürün için bir fabrika yönteminden oluşan bir fabrika arabirimi tanımlayın .
  4. Her platform için, yeni operatöre yapılan tüm başvuruları kapsayan fabrikadan türetilmiş bir sınıf tanımlayın .
  5. İstemci yeni yapılan tüm başvuruları emekli ve kullanması gereken fabrika yöntemleri oluşturmak için ürün nesneleri.

2

Özet Fabrikalar, kod tabanınızı bir arada tutarken birden çok platformu desteklemek için mükemmeldir. Windows, Linux ve OSX üzerinde çalıştırmak istediğiniz büyük bir Qt veya GTK + veya .NET / Mono programınız olduğunu varsayalım. Ancak her platformda farklı bir şekilde uygulanan bir özelliğiniz var (belki kernel32 API veya bir POSIX özelliği aracılığıyla).

public abstract class Feature
{
    public abstract int PlatformSpecificValue { get; }

    public static Feature PlatformFeature
    {
        get
        {
            string platform;
            // do platform detection here
            if (platform == "Win32")
                return new Win32Feature();
            if (platform == "POSIX")
                return new POSIXFeature();
        }
    }

    // platform overrides omitted
}

Bu Soyut Fabrika ile, kullanıcı arayüzünüzün mevcut platform hakkında hiçbir şey bilmesine gerek yoktur.

Feature feature = Feature.PlatformFeature;
Console.WriteLine(feature.PlatformSpecificValue);

1
Anlamıyorum, bu, müşterinin uygulama ayrıntılarını bilmemesi için soyut bir tür döndürmek için fabrika yöntemlerini kullanmaktan ne kadar farklı?
kiwicomb123

1

Tasarım desenlerine bakarsanız, neredeyse tamamı gereksiz hale getirilebilir. Ancak hangi model, benzer türden sorunların çözümü için yaygın olarak kullanılan bir yaklaşım anlamına gelir. Bir tasarım modeli, size bir dizi benzer tasarım problemine tasarım düzeyinde bir yaklaşım veya çözüm sağlar. Tasarım modelini kullanmak, sorununuzu çözmenize ve dolayısıyla daha hızlı teslim etmenize yardımcı olur.



1

Soyut Fabrika modelini abartılı buluyorum.

Her şeyden önce, somutlaştırmak istediğiniz birbiriyle ilişkili bir dizi türe sahip olduğunuz pek sık gerçekleşmez .

İkinci olarak, arabirimler tarafından sağlanan dolaylama (soyutlama) düzeyi, bağımlılık enjeksiyonu ile çalışırken normalde yeterlidir.

WindowsGui vs MacGui'nin tipik bir örneği, bir WindowsButton, MacButton, WindowsScrollBar, MacScrollbar, vs.'nin olduğu yerde Ziyaretçi ve / veya Yorumlayıcı kalıbı kullanarak somut Düğmeler, Kaydırma Çubukları, vb. Tanımlanarak uygulanması genellikle daha kolaydır. gerçek davranış.


bunun için belirli bir amaç var. bağımlılık enjeksiyonu ile servis bulucularını bileşik kökten daha aşağıda istemezsiniz. bunun yerine enjekte edilmiş bir soyut fabrika kullanıyorsunuz.
Adam Tuliper - MSFT

2
iyi ... DI ile servis bulucuyu kullanmak bir anti patteren. Bir Soyut Fabrika, çalışma zamanı değerlerinden BAĞIMLILIKLAR oluşturmamız gerektiğinde evrensel çözümdür.
TheMentor

1

Örneklerinizin tek bir fabrika için çok karmaşık, çok karmaşık ve çirkin ve kullanıcı arayüzünün anlayamayacağı kadar karmaşık olduğu yerlerde basit fabrika kalıbı yerine soyut fabrika kalıbı için bir yer olduğunu düşünüyorum.

Diyelim ki bu tek bir sınıf değil, bir TYPE_A markası .. Diyelim ki 100 çeşit benzer A Tipi bir aile var ve bunlardan bir nesne başlatmanız gerekiyor. Doğru nesneyi birçok benzer türde nesneden oluşan bir markadan çıkarmak için gerekli olan karmaşık bir bilgi olduğunu hayal edin ve bu nesne varlığında hangi parametreleri ayarlayacağınızı ve bunları nasıl ayarlayacağınızı tam olarak bilmeniz gerekir.

Bu markanın özel fabrikasında, onları farklılaştırıp somutlaştıracak tam nesneyi ve aynı zamanda onu nasıl somutlaştıracağımızı alacağız. İnternetten gelen girdilere göre (diyelim ki çevrimiçi mağazada hangi rengin mevcut olduğunu söyleyelim) ve arka planda çalışan diğer uygulamalardan ve hizmetlerden (kullanıcı arayüzünün farkında olmadığı parametreler) bileceğiz.

Ve belki yarın, örneklemek için type_B ve type_C diyelim başka bir ailemiz olacak. Dolayısıyla kullanıcı arayüzünde, kullanıcının bir "tür_A", "tür_B" veya "tür_c" isteyip istemediğini bilmek için "aksi takdirde" seçeneği olacaktır - ancak fabrika sınıfları, türden (aileden) tam olarak hangi sınıfın oluşturulacağına karar verecektir ve nasıl ayarlanacağı - parametrelerine hangi değerlerin ayarlanacağı veya yüklenicisine gönderileceği. Bunların hepsi - kullanıcı arayüzünün farkında olmadığı birçok parametreye göre. Bütün bunlar tek bir fabrika sınıfı için çok fazla olacak.


1

Gerçek hayat örneği, DbConnection, DbCommand ve DbDataAdapter içeren soyut temel sınıflara sahip olan ve System.Data.SqlClient ve System.Data.OracleClient gibi .NET Framework veri sağlayıcıları tarafından paylaşılan System.Data.Common ad alanında sağlanır. bir geliştiricinin, belirli bir veri sağlayıcısına bağlı olmayan genel veri erişim kodu yazmasını sağlar.

DbProviderFactory sınıfı, bir DbProviderFactory örneği oluşturmak için statik yöntemler sağlar. Örnek daha sonra sağlayıcı bilgilerine ve çalışma zamanında sağlanan bağlantı dizesine dayalı olarak doğru bir şekilde yazılmış bir nesne döndürür.

Misal:

 DataTable allProvidersTable = DbProviderFactories.GetFactoryClasses();

görüntü açıklamasını buraya girin

        /* Getting SqlClient family members */
        DbProviderFactory dbProviderFactory = DbProviderFactories.GetFactory("System.Data.SqlClient");
        DbCommand dbCommand = dbProviderFactory.CreateCommand();
        DbConnection dbConnection = dbProviderFactory.CreateConnection();
        DbDataAdapter dbDataAdapter = dbProviderFactory.CreateDataAdapter();

        SqlClientFactory sqlClientFactory = (SqlClientFactory)dbProviderFactory;
        SqlConnection sqlConnection = (SqlConnection)dbConnection;
        SqlCommand sqlCommand = (SqlCommand) dbCommand;
        SqlDataAdapter sqlDataAdapter = (SqlDataAdapter) dbDataAdapter;

        /* Getting OracleClient family members*/
        dbProviderFactory = DbProviderFactories.GetFactory("System.Data.OracleClient");
        dbCommand = dbProviderFactory.CreateCommand();
        dbConnection = dbProviderFactory.CreateConnection();
        dbDataAdapter = dbProviderFactory.CreateDataAdapter();

        OracleClientFactory oracleClientFactory = (OracleClientFactory)dbProviderFactory;
        OracleConnection oracleConnection = (OracleConnection)dbConnection;
        OracleCommand oracleCommand = (OracleCommand)dbCommand;
        OracleDataAdapter oracleDataAdapter = (OracleDataAdapter)dbDataAdapter;

Örnek-2 görüntü açıklamasını buraya girin

Kod Çözümü mimarisi görüntü açıklamasını buraya girin

Somut fabrika örnekleri, aşağıdaki gibi statik Fabrika yöntemi kullanılarak sağlanır

public  class FurnitureProviderFactory
{
    public static IFurnitureFactory GetFactory(string furnitureType)
    {
        if (furnitureType == "Wood")
        {
            return new WoodenFurnitureFactory();
        }
        if (furnitureType == "Plastic")
        {
            return new PlasticFurnitureFactory();
        }
        throw new Exception("Undefined Furniture");
    }
}

0

Sorunuzu doğrudan cevaplamak için, muhtemelen böyle bir tasarım kalıbı kullanmadan kurtulabilirsiniz.

Ancak, gerçek dünyadaki projelerin çoğunun geliştiğini ve projenizi geleceğe hazır hale getirmek için bir tür genişletilebilirlik sağlamak istediğinizi unutmayın.

Kendi deneyimlerime göre, çoğu zaman bir Fabrika uygulanıyor ve proje büyüdükçe Soyut Fabrika gibi daha karmaşık tasarım modellerine dönüşüyor.


0

Her şey bağımlılıklarla ilgili. Sıkı bağlantı ve bağımlılıklar umurunuzda değilse, o zaman soyut bir fabrikaya ihtiyacınız yoktur. Ancak, bakım gerektiren bir uygulama yazdığınız anda önemli olacaktır.


0

Bir.jar oluşturduğunuzu ve başka birinin kavanozunuzu kullandığını ve kodunuzda yeni bir somut nesne kullanmak istediğini varsayalım. Soyut fabrika kullanmıyorsanız, kodunuzu değiştirmesi veya kodunuzun üzerine yazması gerekir. Ancak soyut fabrika kullanıyorsanız, o zaman bir fabrika sağlayabilir ve kodunuza geçebilir ve her şey yolunda.

Geliştirilmiş versiyon: Aşağıdaki senaryoyu düşünün : Bir başkası bir çerçeve yazdı. Çerçeve, çalışma zamanında çok sayıda nesne oluşturmak için soyut bir fabrika ve bazı somut fabrikalar kullanır. Böylece kendi fabrikanızı mevcut çerçeveye kolayca kaydedebilir ve kendi nesnelerinizi oluşturabilirsiniz. Çerçeve, değişikliklere kapalıdır ve soyut fabrika modeli nedeniyle genişletilmesi hala kolaydır.


0

Bu kalıp, özellikle müşteri tam olarak hangi tür yaratacağını bilmediğinde kullanışlıdır. Örnek olarak, sadece cep telefonu satan bir Showroom'un Samsung tarafından üretilen akıllı telefonlar için bir sorgu aldığını varsayalım. Burada, oluşturulacak nesnenin tam türünü bilmiyoruz (bir telefon için tüm bilgilerin somut bir nesne şeklinde sarıldığı varsayılarak). Ancak Samsung tarafından üretilen akıllı telefonlar aradığımızı biliyoruz. Tasarımımızın Soyut fabrika uygulaması varsa, bu bilgiler gerçekten kullanılabilir.

C # 'da Soyut Fabrika Modelini Anlamak ve Uygulamak

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.