Soyut Fabrika ve Fabrika tasarım desenleri arasındaki farklar nelerdir?


456

Bu iki örüntü arasındaki farklar hakkında birçok yazı olduğunu biliyorum, ama bulamadığım birkaç şey var.

Okuduğum kadarıyla, fabrika yöntemi modelinin tek bir beton ürünün nasıl oluşturulacağını tanımlamanıza izin verdiğini, ancak uygulamayı genel bir ürün görecekleri için istemciden gizlediğini görüyorum. İlk sorum soyut fabrika hakkında. Rolü, tek bir somut nesneden ziyade (hangi fabrikayı kullandığınıza bağlı olarak) somut nesne aileleri oluşturmanıza izin vermek mi? Soyut fabrika, aradığınız yöntemlere bağlı olarak yalnızca çok büyük bir nesne mi yoksa birçok nesne mi döndürüyor?

Son iki sorum, çok sayıda yerde gördüğümü tam olarak anlayamadığım tek bir alıntıyla ilgili:

İkisi arasındaki farklardan biri, Soyut Fabrika modeli ile, bir sınıfın, nesne yoluyla örnekleme sorumluluğunu kompozisyon yoluyla başka bir nesneye devrederken, Fabrika Yöntemi modeli miras kullanır ve istenen nesne örneğini işlemek için bir alt sınıfa dayanır.

Anladığım kadarıyla, fabrika yöntem kalıbı, ConcreteCreator'ı hangi ConcreteProduct'un örneklendirileceğini bilmekle sorumlu kılacak bir Creator arayüzüne sahip. Nesne örneklemesini işlemek için miras kullanarak bu ne anlama geliyor?

Şimdi bu alıntıyla ilgili olarak, Soyut Fabrika modeli, nesne somutlaştırma sorumluluğunu kompozisyon yoluyla başka bir nesneye nasıl tam olarak devrediyor? Ne anlama geliyor? Soyut Fabrika paterni de inşaat sürecini gözlerimde yapmak için miras kullanıyor gibi görünüyor, ama sonra yine de bu kalıpları öğreniyorum.

Özellikle son soru ile ilgili herhangi bir yardım çok takdir edilecektir.



İstemci bakış açısından "örneğin nasıl oluşturulduğunu" görmek, teklifi anlamanıza yardımcı olur.
Karthik Bose

@nawfal, bu konudaki cevaplar korkunç.
jaco0646

Yanıtlar:


494

İkisi Arasındaki Fark

"Fabrika yöntemi" ile "soyut fabrika" arasındaki temel fark, fabrika yönteminin tek bir yöntem olması ve soyut fabrikanın bir nesne olmasıdır. Bence birçok insan bu iki terimi karıştırıyor ve birbirlerinin yerine kullanmaya başlıyor. Onları öğrendiğimde farkın tam olarak ne olduğunu bulmakta zorlandığımı hatırlıyorum.

Fabrika yöntemi sadece bir yöntem olduğundan, bir alt sınıfta geçersiz kılınabilir, bu nedenle teklifinizin ikinci yarısı:

... Fabrika Metodu deseni, miras kullanır ve istenen nesne somutlaştırmasını işlemek için bir alt sınıfa dayanır.

Alıntı burada bir nesnenin kendi fabrika yöntemini çağırdığını varsayar . Bu nedenle, dönüş değerini değiştirebilecek tek şey bir alt sınıf olacaktır.

Soyut fabrika, üzerinde birden fazla fabrika yöntemi olan bir nesnedir. Teklifinizin ilk yarısına bakın:

... Soyut Fabrika modeli ile bir sınıf, nesne örneklemesinin sorumluluğunu kompozisyon yoluyla başka bir nesneye devreder ...

Söyledikleri, bir Foo nesnesi yapmak isteyen A nesnesi var. Foo nesnesini kendisi yapmak yerine (örneğin, bir fabrika yöntemiyle), Foo nesnesini oluşturmak için farklı bir nesne (soyut fabrika) alacaktır .

Kod Örnekleri

Size farkı göstermek için kullanılan fabrika yöntemi:

class A {
    public void doSomething() {
        Foo f = makeFoo();
        f.whatever();   
    }

    protected Foo makeFoo() {
        return new RegularFoo();
    }
}

class B extends A {
    protected Foo makeFoo() {
        //subclass is overriding the factory method 
        //to return something different
        return new SpecialFoo();
    }
}

Ve işte kullanılan soyut bir fabrika:

class A {
    private Factory factory;

    public A(Factory factory) {
        this.factory = factory;
    }

    public void doSomething() {
        //The concrete class of "f" depends on the concrete class
        //of the factory passed into the constructor. If you provide a
        //different factory, you get a different Foo object.
        Foo f = factory.makeFoo();
        f.whatever();
    }
}

interface Factory {
    Foo makeFoo();
    Bar makeBar();
    Aycufcn makeAmbiguousYetCommonlyUsedFakeClassName();
}

//need to make concrete factories that implement the "Factory" interface here

15
Bu çok büyük bir açıklama. Ancak, en önemli kısım cevapsız bırakılır ve bu: birini ne zaman ve diğer deseni ne zaman kullanmalı?
croraf

11
Bunun doğru olduğundan emin değilim. Fabrika Metodu, fabrika yöntemlerinden sonra adlandırılan bir tasarım deseni olduğundan emin , ancak sınıf yapısını ve kalıtımını içeriyor. Tek bir yöntem değil.
Aviv Cohn

2
Öyleyse söylemek doğru mu: Fabrika yöntemi, farklı amaçlara sahip tüm düzenli sınıflarda bir yöntem olabilir. Ancak Soyut Fabrika, bir müşteri tarafından kullanılan bir sınıf / nesnedir ve SADECE bir ailede bazı ürünler yaratmaktan sorumlu mudur?
Hieu Nguyen

"SuperFoo" da "Süper" kelimesini kullanmanız sadece özel bir Foo vakası anlamına mı geliyor yoksa aslında süper sınıf mı demek? Tahmin ettiğim gibi bir alt sınıf olmalı.
dahui

@dahui Evet bu bir alt sınıf. Bunun değişiklikleri ettik SpecialFoodaha açık olmak.
Tom Dalling

125

Soyut fabrika , yaratılması gereken nesneler için yöntemleri tanımlayan soyut yöntemlerle bir temel sınıf oluşturur. Temel sınıfı türeten her fabrika sınıfı, her nesne türünün kendi uygulamasını oluşturabilir.

resim açıklamasını buraya girin

Fabrika yöntemi , bir sınıfta nesne oluşturmak için kullanılan basit bir yöntemdir. Genellikle toplama köküne eklenir ( OrderSınıfın bir yöntemi vardır CreateOrderLine)

resim açıklamasını buraya girin

Soyut fabrika

Aşağıdaki örnekte, bir mesajlaşma sisteminden kuyruk oluşturmayı ayırabilmemiz ve böylece kod tabanını değiştirmek zorunda kalmadan farklı kuyruk sistemleri için uygulamalar oluşturabilmemiz için bir arayüz tasarlıyoruz.

interface IMessageQueueFactory
{
  IMessageQueue CreateOutboundQueue(string name);
  IMessageQueue CreateReplyQueue(string name);
}

public class AzureServiceBusQueueFactory : IMessageQueueFactory
{
      IMessageQueue CreateOutboundQueue(string name)
      {
           //init queue
           return new AzureMessageQueue(/*....*/);
      }

      IMessageQueue CreateReplyQueue(string name)
      {
           //init response queue
           return new AzureResponseMessageQueue(/*....*/);
      }

}

public class MsmqFactory : IMessageQueueFactory
{
      IMessageQueue CreateOutboundQueue(string name)
      {
           //init queue
           return new MsmqMessageQueue(/*....*/);
      }

      IMessageQueue CreateReplyQueue(string name)
      {
           //init response queue
           return new MsmqResponseMessageQueue(/*....*/);
      }
}

Fabrika yöntemi

HTTP sunucularındaki sorun, her istek için her zaman bir yanıt almamız gerektiğidir.

public interface IHttpRequest
{
    // .. all other methods ..

    IHttpResponse CreateResponse(int httpStatusCode);
}

Fabrika yöntemi olmadan, HTTP sunucusu kullanıcıları (yani programcılar), IHttpRequestarabirimin amacını bozan uygulamaya özel sınıfları kullanmaya zorlanacaktır .

Bu nedenle, yanıt sınıfının yaratılmasının da soyutlanabilmesi için fabrika yöntemini sunuyoruz.

özet

Fark, bir fabrika yöntemi içeren sınıfın amaçlanan amacının nesne yaratmak değil , soyut bir fabrika ise sadece nesne yaratmak için kullanılmasıdır.

Fabrika yöntemlerini kullanırken dikkatli olunmalıdır, çünkü nesne oluştururken LSP'yi ( Liskov İkame ilkesi ) kırmak kolaydır .


3
Neden somut bir ürüne ihtiyacımız var?
Andrew S

60
Çünkü kimse fikirlere yatırım yapmak istemiyor.
jgauffin

4
Soyut Fabrika Button()"ilgili ürün ailesi" yapmaktan daha fazlasını yaratmalıdır . Örneğin, standart GoF örneği ScrollBar()ve oluşturur Window(). Avantajı, Soyut Fabrikanın birden fazla ürününde ortak bir temayı zorlayabilmesidir.
jaco0646

Jaco haklı. Her iki UML diyagramının da esasen aynı olduğunu düşünün (Abstract Factory UML'nin yanında yanlış). Her iki durumda da, müşteri tek bir ürün oluşturmak için fabrika yöntemini çağırmaktadır.
cobby

1
@AndrewS: Sorunuzu cevaplamak için. Aynı soyutlama (arayüz) için farklı beton ürünlere (sınıflara) ihtiyacımız yoksa, muhtemelen fabrika desenine değil, üretici desenine ihtiyacımız var. (hiç olmadığı kadar iyi geç;))
jgauffin

95

AbstractFactory ve Fabrika tasarım desenleri arasındaki fark aşağıdaki gibidir:

  • Fabrika Yöntemi yalnızca bir ürün oluşturmak için kullanılır, ancak Soyut Fabrika ilgili veya bağımlı ürünlerin ailelerini oluşturmakla ilgilidir.
  • Fabrika Metodu deseni, nesneyi oluşturmak için müşteriye bir yöntem sunarken, Soyut Fabrika durumunda , bu Fabrika yöntemlerinden oluşabilecek ilgili nesne ailesini ortaya koyar .
  • Fabrika Metodu deseni tek bir nesnenin yapımını gizlerken, Soyut Fabrika ilgili nesnelerin bir ailesinin yapımını gizler. Soyut fabrikalar genellikle (bir dizi) fabrika yöntemi kullanılarak uygulanır.
  • Özet Fabrika kalıbı, bir nesneyi yaratma sorumluluğunu başka bir sınıfa devretmek için kompozisyon kullanırken, Fabrika Yöntemi tasarım deseni miras kullanır ve bir nesne oluşturmak için türetilmiş bir sınıfa veya alt sınıfa dayanır.
  • Fabrika Yöntemi deseninin arkasındaki fikir, bir müşterinin çalışma zamanında hangi somut sınıfları oluşturması gerektiğini bilmediği, ancak yalnızca Soyut Fabrika modeli sisteminizin birden fazla ürün ailesi oluşturmak zorunda kaldığı veya uygulama ayrıntılarını göstermeden bir ürün kütüphanesi sağlamak istediğinizde en iyi şekilde kullanılır.!

Fabrika Metodu Desen Uygulaması: Fabrika Metodu UML

Soyut Fabrika Desen Uygulaması:

Soyut fabrika UML


13
Mmm, Soyut Fabrika Örneği'nden emin değilim. Ben şekil fabrikası ve renk fabrikası aynı yöntemleri uygulamak gerektiğini düşünüyorum. Ama sonra haklıysam, o zaman numunenin bir anlamı yok.
Joaquin Iurchuk

4
Mermi noktaları doğrudur; ancak, her iki diyagram da tamamen yanlış ve yanıltıcıdır. Abstract Factory'nin doğru bir modeli için @Trying'daki aşağıdaki şemaya bakın.
jaco0646

1
2 diyagram gerçekten çok yanıltıcı olduğunu kabul etmeliyim. Onları tutorialspoint web sitesinde gördüm ve dürüst olmak gerekirse% 100 onlarla aynı fikirde değilim. Açıklamalar iyi görünüyor
SoftwareDeveloper

Bu çok yanıltıcı.
diyoda_

50+ upvotes ve diyagramlar çok yanlış. SO'da birçok tasarım deseni yanıtına güvenemeyeceğinizi kanıtlayın.
Fuhrmanator

28

Soyut Fabrika ve Fabrika Metodu arasındaki temel fark, Soyut Fabrika'nın Kompozisyon ile uygulanmasıdır ; ancak Fabrika Yöntemi Devralma tarafından uygulanır .

Evet, doğru okudunuz: Bu iki örüntü arasındaki temel fark, eski kompozisyon ve miras tartışmasıdır.

UML diyagramları (GoF) kitabında bulunabilir. Ben kod örnekleri sunmak istiyorum, çünkü ben bu iş parçacığında ilk iki cevap örnekleri birleştirmek ya da tek başına cevap daha iyi bir gösteri verecektir düşünüyorum. Ayrıca, sınıf ve yöntem adlarında kitaptan terminoloji kullandım.

Soyut Fabrika

  1. Burada anlaşılması gereken en önemli nokta, soyut fabrikanın müşteriye enjekte edilmesidir. Bu yüzden Soyut Fabrika'nın Kompozisyon tarafından uygulandığını söylüyoruz. Genellikle, bir bağımlılık enjeksiyon çerçevesi bu görevi yerine getirir; ancak DI için bir çerçeve gerekli değildir.
  2. İkinci kritik nokta, buradaki beton fabrikalarının Fabrika Yöntemi uygulamaları olmamasıdır ! Fabrika Yöntemi için örnek kod aşağıda daha ayrıntılı gösterilmiştir.
  3. Ve son olarak, dikkat edilmesi gereken üçüncü nokta ürünler arasındaki ilişkidir: bu durumda giden ve yanıt kuyrukları. Bir beton fabrikası Azure kuyrukları, diğeri MSMQ üretir. GoF bu ürün ilişkisine "aile" olarak atıfta bulunur ve bu durumda ailenin sınıf hiyerarşisi anlamına gelmediğinin farkında olmak önemlidir.
public class Client {
    private final AbstractFactory_MessageQueue factory;

    public Client(AbstractFactory_MessageQueue factory) {
        // The factory creates message queues either for Azure or MSMQ.
        // The client does not know which technology is used.
        this.factory = factory;
    }

    public void sendMessage() {
        //The client doesn't know whether the OutboundQueue is Azure or MSMQ.
        OutboundQueue out = factory.createProductA();
        out.sendMessage("Hello Abstract Factory!");
    }

    public String receiveMessage() {
        //The client doesn't know whether the ReplyQueue is Azure or MSMQ.
        ReplyQueue in = factory.createProductB();
        return in.receiveMessage();
    }
}

public interface AbstractFactory_MessageQueue {
    OutboundQueue createProductA();
    ReplyQueue createProductB();
}

public class ConcreteFactory_Azure implements AbstractFactory_MessageQueue {
    @Override
    public OutboundQueue createProductA() {
        return new AzureMessageQueue();
    }

    @Override
    public ReplyQueue createProductB() {
        return new AzureResponseMessageQueue();
    }
}

public class ConcreteFactory_Msmq implements AbstractFactory_MessageQueue {
    @Override
    public OutboundQueue createProductA() {
        return new MsmqMessageQueue();
    }

    @Override
    public ReplyQueue createProductB() {
        return new MsmqResponseMessageQueue();
    }
}

Fabrika Yöntemi

  1. Burada anlaşılması gereken en önemli nokta olduğunu ConcreteCreator olduğunu istemcisi. Başka bir deyişle, istemci, üst öğeyi tanımlayan bir alt sınıftır factoryMethod(). Bu nedenle Fabrika Yönteminin Kalıtım tarafından uygulandığını söylüyoruz.
  2. İkinci kritik nokta, Fabrika Metodu Paterninin, Şablon Metodu Paterninin uzmanlaşmasından başka bir şey olmadığını hatırlamaktır. İki desen aynı yapıyı paylaşır. Sadece amaç bakımından farklılık gösterirler. Fabrika Yöntemi yaratıcıdır (bir şey oluşturur), Şablon Yöntemi ise davranışsaldır (bir şey hesaplar).
  3. Ve son olarak, not edilmesi gereken üçüncü nokta, Creator(ebeveyn) sınıfın kendi sınıfını çağırmasıdır factoryMethod(). anOperation()Üst sınıftan çıkarırsak , yalnızca tek bir yöntem bırakarak, artık Fabrika Yöntemi kalıbı olmaz. Başka bir deyişle, Fabrika Yöntemi üst sınıfta ikiden az yöntemle uygulanamaz; biri diğerini çağırmalıdır.
public abstract class Creator {
    public void anOperation() {
        Product p = factoryMethod();
        p.whatever();
    }

    protected abstract Product factoryMethod();
}

public class ConcreteCreator extends Creator {
    @Override
    protected Product factoryMethod() {
        return new ConcreteProduct();
    }
}

Çeşitli. & Muhtelif Fabrika Desenleri

Her ne kadar GoF iki farklı Fabrika modeli tanımlasa da, bunların var olan tek Fabrika modelleri olmadığını unutmayın. Hatta en sık kullanılan Fabrika modelleri bile değildir. Ünlü bir üçüncü örnek Josh Bloch'un Etkili Java'dan Statik Fabrika Kalıbıdır. Head First Tasarım Desenleri kitabı, Simple Factory adını verdikleri başka bir desen daha içeriyor.

Her Fabrika modelinin GoF'den bir tane ile eşleşmesi gerektiğini varsayarak tuzağa düşmeyin.


3
İyi ve iyi örneklere dayanan harika ve çok net bir cevap, IMO'nun bu konusunun en iyisi.
Luke Duda

Harika bir açıklama. Fabrika yöntemi için +1, soyut fabrika yöntemi noktasını çağırmalıdır. Bu nokta ile, bu noktayı anlamadan çok açıktır: eğer onun tarafından çağrılmayan fabrika yöntemimiz varsa, onu oluşturacak başka bir sınıf tarafından kullanılacağını ve alt sınıflarının enjekte edileceğini ima eder, soyut fabrikaya dönüşür , soyut fabrika yönteminin şablon yöntemi deseni gibi fabrika tarafından çağrılması gerektiğinde fark daha az belirginleşir
nits.kk

Bir soru daha. Her factoryMethod()zaman protected "Fabrika Metodu" örüntüsündeki yöntem olmalı mı ? (Evet sanırım)
Yaroslav Fedoruk

1
@YaroslavFedoruk, GoF kitabı publicfabrika yöntemlerine izin veriyor ve yöntemin bile olması gerekmiyor abstract; ancak kritik nokta, yöntemin kalıtım amaçlı olması, dolayısıyla (örneğin) ya staticda olamaz final. Yöntemi yaptım protectedve abstractburada (gerekli) genişletilebilirliği vurgulamak için.
jaco0646

@ nits.kk, ilgili bir cevapla ilgileniyor olabilirsiniz .
jaco0646

26

Özet Fabrika, ilgili ürünler oluşturmak için bir arayüzdür, ancak Fabrika Yöntemi yalnızca bir yöntemdir. Soyut Fabrika birden fazla Fabrika Metodu ile uygulanabilir.

Soyut fabrika UML


10
Aynı cevabı burada zaten gönderdiniz . Bu sorunun benzer olduğunu düşünüyorsanız bunun yerine kopya olarak işaretleyin.
Ja͢ck

11

Kolay anlaşılması için bu örneği düşünün.

Telekomünikasyon şirketleri ne sağlar? Örneğin geniş bant, telefon hattı ve cep telefonu ve ürünlerini müşterilerine sunmak için bir uygulama oluşturmanız istenir.

Genellikle burada yapacağınız şey, yani geniş bant, telefon hattı ve mobil ürünler oluşturmak, bu ürünler için hangi özelliklere sahip olduğunuzu ve oldukça basit olduğunu bildiğiniz Fabrika Metodunuz aracılığıyla yapılır .

Şimdi, şirket müşterilerine geniş bant, telefon hattı ve mobil ürünlerinden oluşan bir paket sunmak istiyor ve işte Soyut Fabrika geliyor .

Özet Fabrika , diğer bir deyişle, kendi ürünlerini oluşturmaktan sorumlu diğer fabrikaların bileşimidir ve Soyut Fabrika bu ürünlerin kendi sorumlulukları açısından nasıl daha anlamlı bir şekilde yerleştirileceğini bilir.

Bu durumda, BundleFactorySoyut Fabrika BroadbandFactory, PhonelineFactoryve MobileFactoryvardır Factory. Daha basitleştirmek için, bu Fabrikalar ayrı ürünleri başlatmak için Fabrika Yöntemi olacaktır .

Aşağıdaki kod örneğine bakın:

public class BroadbandFactory : IFactory {
    public static Broadband CreateStandardInstance() {
        // broadband product creation logic goes here
    }
}

public class PhonelineFactory : IFactory {
    public static Phoneline CreateStandardInstance() {
        // phoneline product creation logic goes here
    }
}

public class MobileFactory : IFactory {
    public static Mobile CreateStandardInstance() {
        // mobile product creation logic goes here
    }
}

public class BundleFactory : IAbstractFactory {

    public static Bundle CreateBundle() {
        broadband = BroadbandFactory.CreateStandardInstance();
        phoneline = PhonelineFactory.CreateStandardInstance();
        mobile = MobileFactory.CreateStandardInstance();

        applySomeDiscountOrWhatever(broadband, phoneline, mobile);
    }

    private static void applySomeDiscountOrWhatever(Broadband bb, Phoneline pl, Mobile m) {
        // some logic here
        // maybe manange some variables and invoke some other methods/services/etc.
    }
}

Bu yardımcı olur umarım.


1
Her staticiki GoF fabrika modelinde de yöntem yoktur . Bu yanlış.
jaco0646

5

Gerçek Hayat Örneği. (Hatırlaması kolay)

Fabrika

Bir ev inşa ettiğinizi ve bir kapı marangozuna yaklaştığınızı düşünün. Kapı ve gereksinimleriniz için ölçüm verirsiniz ve o sizin için bir kapı inşa eder. Bu durumda, marangoz bir kapı fabrikasıdır. Spesifikasyonlarınız fabrika için girişlerdir ve kapı fabrikadan çıktı veya üründür.

Soyut Fabrika

Şimdi, aynı kapı örneğini düşünün. Bir marangoza gidebilir veya plastik bir kapı dükkanına veya PVC dükkanına gidebilirsiniz. Hepsi kapı fabrikaları. Duruma göre ne tür bir fabrikaya yaklaşmanız gerektiğine siz karar verirsiniz. Bu bir Soyut Fabrika gibi.

Burada hem fabrika yöntemi kalıbını hem de soyut fabrika kalıbını, sorunları açıklamaktan ve sonra yukarıdaki kalıpları kullanarak sorunları çözmekten başlayarak açıkladım https://github.com/vikramnagineni/Design-Patterns/tree/master


3

Üretim kodunda çoğu zaman soyut fabrika desenini kullandığımızı açıklığa kavuşturalım çünkü A sınıfı B arayüzü ile programlanmıştır. Ve A'nın B örnekleri oluşturması gerekir. Bu yüzden A'nın B örnekleri üretmek için bir fabrika nesnesine sahip olması gerekir. Yani A, B'nin somut bir örneğine bağımlı değildir. Umarım yardımcı olur.


3

Motivasyonlardaki farklılıkları anlayın:

Varsayalım ve nesnelerin birbirleriyle olan ilişkilerinin somut bir şekilde uygulandığı bir araç oluşturduğunuzu varsayalım. Nesnelerdeki varyasyonları öngördüğünüz için, başka bir nesneye nesnelerin varyantlarını oluşturma sorumluluğunu atayarak bir dolaylılık yarattınız ( buna soyut fabrika diyoruz ). Bu soyutlama, bu nesnelerin varyantlarına ihtiyaç duyan gelecekteki uzantıları öngördüğünüz için güçlü bir fayda sağlar.

Bu düşünce çizgisindeki oldukça ilginç bir motivasyon, tüm gruptaki nesnelerin her birinin veya hiçbirinin karşılık gelen bir varyanta sahip olacağı bir durumdur. Bazı koşullara bağlı olarak, değişkenlerden herhangi biri kullanılır ve her durumda tüm nesneler aynı varyantta olmalıdır. Bu, bir nesnenin varyantları ortak bir tek tip sözleşmeyi ( daha geniş anlamda arayüz) takip ettikleri sürece , somut uygulama kodunun asla kırılmaması gerektiğini düşündüğümüzden anlamak için biraz sezgisel olabilir . Buradaki ilginç gerçek şu ki, özellikle beklenen davranış bir programlama sözleşmesi ile modellenemediğinde bu her zaman doğru değildir.

Basit ( fikri GoF'den ödünç almak ) herhangi bir GUI uygulaması, MS veya Mac veya Fedora OS'lerin görünüşünü taklit eden bir sanal monitör söylüyor. Burada, örneğin, pencere, düğme vb. Tüm widget nesneleri MAC varyantından türetilen bir kaydırma çubuğu dışında MS varyantına sahip olduğunda, aracın amacı kötü bir şekilde başarısız olur.

Yukarıdaki durumlar, Soyut Fabrika Şablonunun temel ihtiyacını oluşturmaktadır .

Öte yandan, birçok kişinin çerçevenizi kullanarak çeşitli araçlar ( örneğin yukarıdaki örneklerde olduğu gibi ) oluşturabileceği bir çerçeve yazdığınızı düşünün . Bir çerçeve fikriyle, mantığınızda somut nesneler kullanamasanız da, buna gerek yoktur. Çeşitli nesneler ve bunların nasıl etkileştikleri arasında bazı üst düzey sözleşmeler yapmayı tercih edersiniz. Siz ( bir çerçeve geliştiricisi olarak ) çok soyut bir düzeyde kalırken, aracın her kurucuları çerçeve yapılarınızı takip etmek zorunda kalırlar. Bununla birlikte, onlar ( araç üreticileri ) hangi nesnenin inşa edileceğine ve oluşturdukları tüm nesnelerin nasıl etkileşime gireceğine karar verme özgürlüğüne sahiptir. Önceki durumdan farklı olarak ( Soyut Fabrika Deseni ), siz ( çerçeve yaratıcısı olarak)) bu durumda somut nesnelerle çalışmanıza gerek yoktur; daha ziyade nesnelerin sözleşme düzeyinde kalabilir. Dahası, önceki motivasyonların ikinci kısmından farklı olarak, siz veya araç üreticileri asla varyantlardan nesneleri karıştırma durumlarına sahip değildir. Burada, çerçeve kodu sözleşme düzeyinde kalırken, her araç üreticisi ( davanın doğası gereği ) kendi nesnelerini kullanmakla sınırlıdır . Bu durumda nesne oluşturma işlemleri her uygulayıcıya devredilir ve çerçeve sağlayıcıları yalnızca nesne oluşturma ve döndürme için tek tip yöntemler sağlar. Bu tür yöntemler, çerçeve geliştiricisinin kodlarıyla devam etmesi için kaçınılmazdır ve Fabrika yöntemi ( altta yatan model için Fabrika Yöntem Kalıbı) adı verilen özel bir ada sahiptir .

Birkaç Not:

  • 'Şablon yöntemi' konusunda bilginiz varsa, herhangi bir çerçeve biçimiyle ilgili programlar olması durumunda fabrika yöntemlerinin genellikle şablon yöntemlerinden çağrıldığını görürsünüz. Buna karşılık, uygulama programlarının şablon yöntemleri genellikle belirli algoritmanın basit uygulanması ve fabrika yöntemlerinin boşluğudur.
  • Ayrıca, düşüncelerin bütünlüğü için, ( yukarıda belirtilen ) çerçeveyi kullanarak, bir araç üreticisi bir araç inşa ederken, her fabrika yönteminin içinde, somut bir nesne oluşturmak yerine, sorumluluğu bir özete devredebilir -yapıcı nesne, araç üreticisi gelecekteki genişletmeler için beton nesnelerin varyasyonlarını öngörmesi koşuluyla.

Basit kod:

//Part of framework-code
BoardGame {
    Board createBoard() //factory method. Default implementation can be provided as well
    Piece createPiece() //factory method

    startGame(){        //template method
         Board borad = createBoard()
         Piece piece = createPiece()
         initState(board, piece)
    }
}


//Part of Tool-builder code
Ludo inherits  BoardGame {
     Board createBoard(){ //overriding of factory method
         //Option A: return new LudoBoard() //Lodu knows object creation
         //Option B: return LudoFactory.createBoard() //Lodu asks AbstractFacory
     }
….
}

//Part of Tool-builder code
Chess inherits  BoardGame {
    Board createBoard(){ //overriding of factory method
        //return a Chess board
    }
    ….
}

3
  1. İlk sorum soyut fabrika hakkında. Rolü, tek bir somut nesneden ziyade (hangi fabrikayı kullandığınıza bağlı olarak) somut nesne aileleri oluşturmanıza izin vermek mi?

Evet. Soyut Fabrikanın amacı:

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


  1. Soyut fabrika, aradığınız yöntemlere bağlı olarak yalnızca çok büyük bir nesne mi yoksa birçok nesne mi döndürüyor?

İdeal olarak, istemcinin çağırdığı yöntem başına bir nesne döndürmesi gerekir.

  1. Anladığım kadarıyla, fabrika yöntem kalıbı, ConcreteCreator'ı hangi ConcreteProduct'un örneklendirileceğini bilmekle sorumlu kılacak bir Creator arayüzüne sahip. Nesne örneklemesini işlemek için miras kullanarak bu ne anlama geliyor?

Evet. Fabrika yönteminde kalıtım kullanılır.

  1. Özet Fabrika düzeni, nesne oluşturma sorumluluğunu kompozisyon yoluyla başka bir nesneye devrediyor mu? Ne anlama geliyor?

AbstractFactory bir Fabrika tanımlar Metod ve ConcreteFactory, bir ConcreteProduct oluşturmaktan sorumludur. Sadece bu makaledeki kod örneğini takip edin .

İlgili SE yayınlarında daha fazla ayrıntı bulabilirsiniz:

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

Tasarım Desenleri: Fabrika vs Fabrika yöntemi vs Soyut Fabrika


3

Fabrika Yöntemi mirasa dayanır: Nesne oluşturma, nesne oluşturmak için fabrika yöntemini uygulayan alt sınıflara devredilir.

Özet Fabrika , nesne kompozisyonuna dayanır: nesne oluşturma, fabrika arayüzünde gösterilen yöntemlerde uygulanır.

Fabrika ve Soyut fabrika modelinin yüksek seviye diyagramı,

diyagram

Fabrika yöntemi hakkında daha fazla bilgi için bu makaleye bakın .

Soyut fabrika yöntemi hakkında daha fazla bilgi için bu makaleye bakın .


2

Minimum arayüz ile çok basit hale getirmek için lütfen "// 1" e odaklanın:

class FactoryProgram
    {
        static void Main()
        {
            object myType = Program.MyFactory("byte");
            Console.WriteLine(myType.GetType().Name);

            myType = Program.MyFactory("float"); //3
            Console.WriteLine(myType.GetType().Name);

            Console.ReadKey();
        }

        static object MyFactory(string typeName)
        {
            object desiredType = null; //1
            switch (typeName)
            {
                case "byte": desiredType = new System.Byte(); break; //2
                case "long": desiredType = new System.Int64(); break;
                case "float": desiredType = new System.Single(); break;
                default: throw new System.NotImplementedException();
            }
            return desiredType;
        }
    }

Burada önemli noktalar: 1. Fabrika ve Özet Fabrika mekanizmaları kalıtım (System.Object-> byte, float ...) kullanmalıdır; böylece programda kalıtım varsa o zaman Fabrika (Soyut Fabrika büyük olasılıkla orada olmaz) tasarım 2 zaten oradadır. Yaratıcı (MyFactory) beton türü bilir böylece beton türü nesnesini arayan (Main) döndürür; Soyut fabrikada dönüş tipi bir Arayüz olacaktır.

interface IVehicle { string VehicleName { get; set; } }
interface IVehicleFactory
    {
        IVehicle CreateSingleVehicle(string vehicleType);
    }
class HondaFactory : IVehicleFactory
    {
        public IVehicle CreateSingleVehicle(string vehicleType)
        {
            switch (vehicleType)
            {
                case "Sports": return new SportsBike();
                case "Regular":return new RegularBike();
                default: throw new ApplicationException(string.Format("Vehicle '{0}' cannot be created", vehicleType));
            }
        }
    }
class HeroFactory : IVehicleFactory
    {
        public IVehicle CreateSingleVehicle(string vehicleType)
        {
            switch (vehicleType)
            {
                case "Sports":  return new SportsBike();
                case "Scooty": return new Scooty();
                case "DarkHorse":return new DarkHorseBike();
                default: throw new ApplicationException(string.Format("Vehicle '{0}' cannot be created", vehicleType));
            }
        }
    }

class RegularBike : IVehicle { public string VehicleName { get { return "Regular Bike- Name"; } set { VehicleName = value; } } }
class SportsBike : IVehicle { public string VehicleName { get { return "Sports Bike- Name"; } set { VehicleName = value; } } }
class RegularScooter : IVehicle { public string VehicleName { get { return "Regular Scooter- Name"; } set { VehicleName = value; } } }
class Scooty : IVehicle { public string VehicleName { get { return "Scooty- Name"; } set { VehicleName = value; } } }
class DarkHorseBike : IVehicle { public string VehicleName { get { return "DarkHorse Bike- Name"; } set { VehicleName = value; } } }

class Program
{
    static void Main(string[] args)
    {
        IVehicleFactory honda = new HondaFactory(); //1
        RegularBike hondaRegularBike = (RegularBike)honda.CreateSingleVehicle("Regular"); //2
        SportsBike hondaSportsBike = (SportsBike)honda.CreateSingleVehicle("Sports");
        Console.WriteLine("******* Honda **********"+hondaRegularBike.VehicleName+ hondaSportsBike.VehicleName);

        IVehicleFactory hero = new HeroFactory();
        DarkHorseBike heroDarkHorseBike = (DarkHorseBike)hero.CreateSingleVehicle("DarkHorse");
        SportsBike heroSportsBike = (SportsBike)hero.CreateSingleVehicle("Sports");
        Scooty heroScooty = (Scooty)hero.CreateSingleVehicle("Scooty");
        Console.WriteLine("******* Hero **********"+heroDarkHorseBike.VehicleName + heroScooty.VehicleName+ heroSportsBike.VehicleName);

        Console.ReadKey();
    }
}

Önemli noktalar: 1. Gereksinim: Honda "Düzenli", "Spor", ancak Kahraman "DarkHorse", "Spor" ve "Scooty" oluşturacaktı. 2. neden iki arayüz? Biri üretici tipi (IVehicleFactory) ve diğeri ürün fabrikası (IVehicle) için; 2 arayüzü anlamak için diğer bir yol soyut fabrika tamamen ilgili nesneleri 2 oluşturmaktır. Yakalama IVehicleFactory dönen çocuklar ve IVehicle (fabrikada beton yerine); böylece üst değişken (IV araç) alıyorum; daha sonra CreateSingleVehicle'ı çağırarak ve sonra gerçek alt nesneye üst nesneyi dökerek gerçek somut tür oluşturuyorum. Yaparsam ne olur RegularBike heroRegularBike = (RegularBike)hero.CreateSingleVehicle("Regular");; ApplicationException alacaksınız ve bu yüzden gerekirse açıklayacağım genel soyut fabrikaya ihtiyacımız var.


1

Soyut Fabrika : Bir fabrika fabrikası; Bireysel ancak ilgili / bağımlı fabrikaları somut sınıflarını belirtmeden birlikte gruplandıran bir fabrika. Soyut Fabrika Örneği

Fabrika : Örnekleme mantığını çocuk sınıflarına devretmenin bir yolunu sunar. Fabrika Desen Örneği


0

Ben her zaman Fabrika Yöntemi üzerinde Soyut Fabrika tercih ediyorum. Tom Dalling'in yukarıdaki örneğinden (büyük açıklama btw), Soyut Fabrikanın yapmamız gereken tek şey, farklı bir Fabrikayı kurucuya (burada kullanılan kurucu bağımlılığı enjeksiyonu) geçmek olduğu için daha kompozit olabilir. Ancak Fabrika Yöntemi, yeni bir sınıf (yönetilecek daha fazla şey) tanıtmamızı ve alt sınıflamayı kullanmamızı gerektirir. Her zaman kompozisyonu kalıtım yerine tercih edin.


0

tam olarak söylememe izin ver. cevapların çoğu zaten açıklanmış, şemalar ve örnekler verilmiştir. bu yüzden anwer'ım sadece bir astar olurdu. kendi sözlerim: - “soyut fabrika deseni, çoklu fabrika yöntemi uygulamaları üzerinden soyut katmana eklenir. soyut fabrikanın bir veya daha fazla fabrika metodu deseni içerdiği veya birleştirdiği anlamına gelir ”


Bu doğru değil. Bu, Soyut Fabrikanın bir fabrika fabrikasından başka bir şey olmadığı hakkında çok yaygın bir yanılgıdır.
jaco0646

0

Yukarıdaki cevapların birçoğu Soyut Fabrika ve Fabrika Metodu modeli arasında kod karşılaştırmaları sağlamaz. Java ile açıklamaya çalışıyorum. Umarım basit bir açıklamaya ihtiyacı olan birine yardımcı olur.

GoF'ın uygun şekilde söylediği gibi: Soyut Fabrika, somut sınıflarını belirtmeden ilgili veya bağımlı nesnelerin ailelerini oluşturmak için bir arayüz sağlar.

        public class Client {
            public static void main(String[] args) {
               ZooFactory zooFactory = new HerbivoreZooFactory();       
               Animal animal1 = zooFactory.animal1();
               Animal animal2 = zooFactory.animal2();
               animal1.sound();
               animal2.sound();

               System.out.println();

               AnimalFactory animalFactory = new CowAnimalFactory();
               Animal animal = animalFactory.createAnimal();
               animal.sound();
            }
        }

        public interface Animal {
            public void sound();
        }

        public class Cow implements Animal {

            @Override
            public void sound() {
                System.out.println("Cow moos");
            }

        }

        public class Deer implements Animal {

            @Override
            public void sound() {
                System.out.println("Deer grunts");
            }

        }

        public class Hyena implements Animal {

            @Override
            public void sound() {
                System.out.println("Hyena.java");
            }

        }

        public class Lion implements Animal {

            @Override
            public void sound() {
                System.out.println("Lion roars");
            }

        }

        public interface ZooFactory {
            Animal animal1();

            Animal animal2();
        }

        public class CarnivoreZooFactory implements ZooFactory {

            @Override
            public Animal animal1() {
                return new Lion();
            }

            @Override
            public Animal animal2() {
                return new Hyena();
            }

        }

        public class HerbivoreZooFactory implements ZooFactory{

            @Override
            public Animal animal1() {
                return new Cow();
            }

            @Override
            public Animal animal2() {
                return new Deer();
            }

        }

        public interface AnimalFactory {
            public Animal createAnimal();
        }

        public class CowAnimalFactory implements AnimalFactory{

            @Override
            public Animal createAnimal() {
                return new Cow();
            }

        }

        public class DeerAnimalFactory implements AnimalFactory{

            @Override
            public Animal createAnimal() {
                return new Deer();
            }

        }

        public class HyenaAnimalFactory implements AnimalFactory{

            @Override
            public Animal createAnimal() {
                return new Hyena();
            }

        }

        public class LionAnimalFactory implements AnimalFactory{

            @Override
            public Animal createAnimal() {
                return new Lion();
            }

        }

Bu doğru değil. Bu kod, Soyut Fabrikanın bir fabrika fabrikasından başka bir şey olmadığı gibi çok yaygın bir yanlış kanı uygular.
jaco0646

1
@ jaco0646 Fabrika metodu modelinde, odağın FactoryImpl'den sadece bir somut ürün almak olduğuna inanıyorum. Oysa soyut fabrika modelinde, FactoryImpls, Fabrika arayüzünün bir sözleşme sağladığı birçok benzer / ilgili Beton Ürününü sağlamaktan sorumludur. Yani ZooFactory, bir fabrika fabrikası değil, dediğin gibi, sadece Impls birbirleriyle ilişkili Beton Ürünleri sağlayan bir arayüz. Kabul etmezseniz anlayışımı düzeltmekten çekinmeyin.
Jatin Shashoo

Fabrika Yöntemi'nde odak, alt sınıflandırma yoluyla kalıtım üzerinedir, çünkü Fabrika Yöntemi, Şablon Yöntemi deseninin bir uzmanlığıdır. Yukarıdaki en çok oy alan cevap iyi bir kod örneği göstermektedir.
jaco0646

@ jaco0646 1. Bu, yukarıdaki örnekte, AnimalFactory için arabirimler kullanmak ve uygulamalarını sağlamak yerine, bir sınıf kullanmalı ve alt sınıflarında createAnimal () yöntemini geçersiz kılmalıyım: CowAnimalFactory, LionAnimalFactory, vb. 2. Ayrıca, ZooFactory için gösterilen örnek hakkında ne düşünüyorsunuz ??
Jatin Shashoo

İlk soruya: evet. İkincisi, her bir yanıtı eleştirmeye devam etmek yerine bu konuya kendi cevabımı ekledim.
jaco0646
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.