2010-11-04 16 views
6

Bu tasarım deseninin bir açıklamasını ve kod örneğini bir araya getiriyorum; etrafımdaki diğer kişilere yardım etmeyi denemeye çalışıyorum (ayrıca kalıba hakim olmama yardımcı olmakla birlikte).Fabrika Tasarım Örneği (gereklilik eleştirisi)

Aramak istediklerim & veya benim açıklama ve kod örnekimin eleştirisi ... teşekkürler!

Fabrika modeli nedir? Fabrika düzeni, gerçek bir dünya fabrikasına benzer şekilde - nesnelerin oluşturulmasının - ve çoğu kez - oluşturulmasının işlenmesi için özel bir "nesne yaratıcısı nesnesi" kullanır. otomobillerin çeşitli yaratıcısı olan bir otomobil fabrikasının

Gerçek hayattan örnek
düşünün. Bu otomobil fabrikasındaki montaj hatlarından biri bir gün bir kamyon üretebilir, ancak başka bir günde araba üretmek için yeniden kullanılabilir. Bir bayilikten, tahsis edilen hesap işlem departmanına 10 araba siparişi verdiğinizi varsayalım. Bu departman belli bir fabrikayı kullanır ve 10 araba sipariş eder. Hesap işleyicileri, otomobilleri kendileri yapmakla (kötü sonuçları hayal etmemekle) ilgilenmezler, sadece son ürünle çalışırlar, bayilerin araçlarını almasını sağlarlar.

Gelecek yıl aynı otomobilin yeni bir modeli ortaya çıkıyor ve siparişler akmaya başlıyor. Hesap işleyicileri (hala otomobil üretimiyle ilgili değil) siparişleri yerleştiriyorlar, ancak şimdi aldıkları araba farklı. montaj yöntemi veya belki de fabrika tamamen farklı olabilir, ancak hesap işleyicileri bunun için endişelenmemelidir. Ek bir düşünce: Araçların fabrika montajcıları, belirli bir hesap işleyicisi bir sipariş verdiğinde (örneğin hesap işleyicisi X bir sipariş verdiğinde, ne yapması gerektiğini tam olarak bilir), fabrika montajcısı, hesap işleyicisi X için, Y tipi 10 araç ürettiklerini bilir). Başka bir seçenek, hesap işleyicisinin, montajcıya tam olarak ne tür bir araç üreteceğini söylemesi olabilir.

Hesap işleyicileri de taşıtların oluşturulmasını ele geçirdiyse (diğer bir deyişle, eşleştirildiklerinde), bir araç herhangi bir şekilde her değiştiğinde, her bir hesap işleyicisinin bu aracı üretirken yeniden incelenmesi gerekir. Bu, kalite sorunları yaratacaktır, çünkü fabrikalardan çok daha fazla hesap işleyicisi vardır ... hatalar olur, masraf çok daha büyük olur. OOP geri Turlu


yazılım mühendisliği uygulanmış bir tasarım deseni konsepti yukarıdaki örneğe benzer olarak bir nesne fabrika ... fabrika diğer nesnelerin çeşitli yayıklar, bir montaj hattı kullanabilir (nesne Belirli bir nesne türünü üreten assembler), belirli bir şekilde döndü. Birleştirici, istekte bulunan istemciyi denetleyebilir ve işleyebilir veya istemci, assembler'a hangi nesnenin gerektirdiğini söyleyebilir. Şimdi ... bir projede bulunuyorsunuz ve bir nesne fabrikası ve çeşitli montajcılar yaratıyorsunuz, daha sonra projedeki yolda ilerliyorsunuz, gereksinimler biraz değişiyor, artık nesne içeriklerini ve müşterilerinin bu nesneyi nasıl ele aldıklarını değiştirmeniz isteniyor. Fabrika modelini kullandığınız için bu basit bir değişikliktir ve tek bir konumda, fabrikanın ürettiği nesneleri değiştirebilir veya ekleyebilirsiniz ve birleştiricilerin nesne içeriğini dışarıda bıraktığı biçimi değiştirebilirsiniz.

Bunu yapmanın talihsiz yolu, bir fabrika yöntemi olmaksızın, her nesne örneğini başlatıp, istemcilerin kendileri içindekileri biçimlendirmek olurdu ... bu belirli nesneyi 20 istemciden kullandığını söylüyorsunuz. Şimdi her bir müşteriye gitmeli, nesne örneklerini ve formatlarını değiştirmelisin ... ne zaman kaybı ... Ne tembel ol ... ilk kez doğru şekilde yap, böylece kendini (ve başkalarını) kurtar ve daha sonra çaba.

Kod örneği (C#)
Aşağıda gıda ve çeşitli yiyecek için bir fabrika kullanan bir örnektir

Factory module 
    public enum FoodType 
    { 
    //enumerated foodtype value, if client wants to specify type of object, coupling still occurs 
     Hamburger, Pizza, HotDog 
    } 
  
    /// <summary> 
    /// Object to be overridden (logical) 
    /// </summary> 
    public abstract class Food 
    { 
     public abstract double FoodPrice { get; } 
    } 
  
    /// <summary> 
    /// Factory object to be overridden (logical) 
    /// </summary> 
    public abstract class FoodFactory 
    { 
     public abstract Food CreateFood(FoodType type); 
    } 
  
    //------------------------------------------------------------------------- 
    #region various food objects 
    class Hamburger : Food 
    { 
     double _foodPrice = 3.59; 
     public override double FoodPrice 
     { 
      get { return _foodPrice; } 
     } 
    } 
  
    class Pizza : Food 
    { 
     double _foodPrice = 2.49; 
     public override double FoodPrice 
     { 
      get { return _foodPrice; } 
     } 
    } 
  
    class HotDog : Food 
    { 
     double _foodPrice = 1.49; 
     public override double FoodPrice 
     { 
      get { return _foodPrice; } 
     } 
    } 
    #endregion 
    //-------------------------------------------------------------------------- 
  
  
    /// <summary> 
    /// Physical factory 
    /// </summary> 
    public class ConcreteFoodFactory : FoodFactory 
    { 
     public override Food CreateFood(FoodType foodType) 
     { 
      switch (foodType) 
      { 
       case FoodType.Hamburger: 
        return new Hamburger(); 
        break; 
       case FoodType.HotDog: 
        return new HotDog(); 
        break; 
       case FoodType.Pizza: 
        return new Pizza(); 
        break; 
       default: 
        return null; 
        break; 
      } 
     } 
    } 
  
    /// <summary> 
    /// Assemblers 
    /// </summary> 
    public class FoodAssembler 
    { 
     public string AssembleFoodAsString(object sender, FoodFactory factory) 
     { 
      Food food = factory.CreateFood(FoodType.Hamburger); 
      if (sender.GetType().Name == "default_aspx") 
      { 
       return string.Format("The price for the hamburger is: ${0}", food.FoodPrice.ToString()); 
      } 
      else 
      { 
       return food.FoodPrice.ToString(); 
      } 
     } 
  
     public Food AssembleFoodObject(FoodFactory factory) 
     { 
      Food food = factory.CreateFood(FoodType.Hamburger); 
      return food; 
     } 
    } 

Calling factory 
FoodFactory factory = new ConcreteFoodFactory(); //create an instance of the factoryenter code here 
lblUser.Text = new FoodAssembler().AssembleFoodAsString(this, factory); //call the assembler which formats for string output 

Object o = new FoodAssembler().AssembleFoodObject(factory); //example: instantiating anon object, initialized with created food object 
+0

Topluluk wiki, belki? –

+0

Niçin yakın oy? Soru biraz uzun olmasına rağmen, bu geçerlidir, – jgauffin

cevap

14

Üzgünüz. Bu oldukça karmaşık bir fabrikadır. Yansıma bazı POWWAH giva!

public interface IFood 
{ 
    bool IsTasty { get; } 
} 
public class Hamburger : IFood 
{ 
    public bool IsTasty {get{ return true;}} 
} 
public class PeaSoup : IFood 
{ 
    public bool IsTasty { get { return false; } } 
} 

public class FoodFactory 
{ 
    private Dictionary<string, Type> _foundFoodTypes = 
     new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase); 

    /// <summary> 
    /// Scan all specified assemblies after food. 
    /// </summary> 
    public void ScanForFood(params Assembly[] assemblies) 
    { 
     var foodType = typeof (IFood); 
     foreach (var assembly in assemblies) 
     { 
      foreach (var type in assembly.GetTypes()) 
      { 
       if (!foodType.IsAssignableFrom(type) || type.IsAbstract || type.IsInterface) 
        continue; 
       _foundFoodTypes.Add(type.Name, type); 
      } 
     } 

    } 

    /// <summary> 
    /// Create some food! 
    /// </summary> 
    /// <param name="name"></param> 
    /// <returns></returns> 
    public IFood Create(string name) 
    { 
     Type type; 
     if (!_foundFoodTypes.TryGetValue(name, out type)) 
      throw new ArgumentException("Failed to find food named '" + name + "'."); 

     return (IFood)Activator.CreateInstance(type); 
    } 

} 

Kullanımı:

Düzenleme kodunuzu üzerinde geribildirim
var factory = new FoodFactory(); 
factory.ScanForFood(Assembly.GetExecutingAssembly()); 

Console.WriteLine("Is a hamburger tasty? " + factory.Create("Hamburger").IsTasty); 

: Herşeyden

First, fabrikalar zaman mümkün olduğunca küçük bir kod değişiklikleri ile nesneleri oluşturmak edebilmek için kullanılır yeni tür uygulamaların eklenmesi. Enum kullanmak, fabrikaya çağrılan tüm yerlerin bir enum kullanması ve enum değiştiğinde güncellenmesi gerektiği anlamına gelir.

Elbette, türleri doğrudan oluşturmaktan biraz daha iyi.

Kodunuzdaki ikinci sorun, bir anahtar deyimi kullanmanızdır (ancak, enum bir gereklilikse bunu yapmanın en iyi yoludur). Tüm farklı sınıfları bir şekilde kayıt altına almak daha iyidir. Bir yapılandırma dosyasından veya gerçek uygulamaların (örneğin Hamburger sınıfı) kendilerini kaydettirmelerine izin vererek. Bu, fabrikanın singleton desenini takip etmesini gerektirir.

İşte kurtarma için Yansıma geliyor. Yansıma, DLL ve EXE'lerde her türden geçmenize izin verir. Böylece arayüzümüzü uygulayan tüm sınıfları arayabilir ve bu nedenle tüm sınıfları bir sözlük oluşturabiliriz.

+0

umduğum geri bildirim türü, benim örnek hakkında yorum yapmak için bir örnek açıklayan benim örnek üzerine yorum yapabilirsiniz Deseni daha önce hiç duymadın mı? Örneğimin doğru ve mantıklı olduğundan emin olmamalıyım. Giriş için teşekkürler, cevap olarak işaretleyin. – dbobrowski

+0

Bunun yerine, generikleri kullanabileceğiniz zaman yansıma kullanın, bir dosyadan veya benzer bir şeyden yiyecek türlerini okumak istemediğiniz sürece, sınıf adlarına yönelik dizelerin kullanımı, yalnızca daha fazla hata yapmaya başlayacaktır. – Doggett

+0

"Hamburger" demek, uygulamanın neye benzediğini hiçbir şekilde belirleyemez. Fabrikayı söyleyerek. (), tüm uygulamalarınızı Hamburger'den türetmeye zorlar. Dize alternatifi ile ilgili başka bir şey de, kodun (örneğin dinamik olarak yüklenmiş bir gruptan) herhangi bir bilgisinin olmadığı uygulamaları kullanabilmesidir. – jgauffin

0

Ben bunun yerine soyut sınıflar/devralma arayüzleri kullanmak öneririm nesneleri. Bunun dışında, iyi görünüyor.

+2

Noooooo. Anahtar ifadeleri ve enums – jgauffin

3

Bence gerçek dünya örneğini içeren açıklamanız iyi. Bununla birlikte, örnek kodunuzun desenin gerçek faydalarını gösterdiğini düşünmüyorum.

bazı olası değişiklikler: Ben tiplerine paralel olarak enum olmazdı

  • . Bu, her eklendiğinde enonu güncellemeniz gerektiği gibi görünüyor. System.Type geçirilmesi daha uygun olabilir. Daha sonra, fabrikayı şablon argümanına sahip bir jenerik bile yapabilirsiniz.
  • Donanım arabirimi gibi bir şey oluşturmak için kullanırsanız, desen daha "etkileyici" olduğunu düşünüyorum. Daha sonra bir "AbstractNetworkDevice" sahibi olursunuz ve tüm arayanlarınız hangi donanım kurulumuna sahip olduğunuzu bilmez. Ancak, fabrika bir "TcpNetworkDevice" veya bir "SerialNetworkDevice" oluşturabilir veya başlangıçta yapılan bazı yapılandırmalara dayanarak ne yapabilir.
+0

kullanmak için Tamam değil tavsiye phillipp için, ben bu bir, ama yine de çok yeni – dbobrowski