代码之家  ›  专栏  ›  技术社区  ›  Jeff Meatball Yang

此代码中的设计模式是什么?

  •  1
  • Jeff Meatball Yang  · 技术社区  · 16 年前

    假设我有一个singleton ish、factory ish、reflection ish类,它接收一些输入,并返回某个接口的具体实现的新实例。这是什么样的设计?有没有更好的方法来做我想做的事?

    下面是一些代码来说明这一点:

    using System;
    using System.Collections.Generic;
    
    // static factory class
    public static class ArticleFactory 
    {
        // given an SKU, store the Type object for an IArticle object
        private static Dictionary<string, Type> articleRegistry = new Dictionary<string, Type>();
    
        // allow public registration of SKU-to-Type object relationships
        public static bool Register(string sku, Type typeInfo)
        {
            if(!articleRegistry.ContainsKey(sku)) 
            {
                articleRegistry.Add(sku, typeInfo);
                return true;
            }
            return false;
        }
    
        // given a SKU, give me an instance of the related IArticle object
        public static IArticle NewArticle(string sku)
        {
            if(articleRegistry.ContainsKey(sku))
            {
                // use reflection to invoke the default constructor
                return articleRegistry[sku].GetConstructor(Types.EmptyTypes).Invoke(null) as IArticle;
            }
            return null;
        }
    }
    
    // example concrete-implementation of an IArticle
    public class Jeans : IArticle 
    {
        public decimal GetPrice() {  return SomeDecimal(); }
    }
    
    // WHERE DO I CALL THIS LINE? 
    ArticleFactory.Register("0929-291", typeof(Jeans)); 
    
    // Later on, if another group needs to write the class for Snowboards, 
    // how can they self-register their class, without changing any "Main()"
    // or "Page_Init()" function?
    
    4 回复  |  直到 8 年前
        1
  •  2
  •   Aaronaught    16 年前

    看起来你已经确定了模式。这是最重要的 Factory Method Pattern . 或者更确切地说,这是一个有点不成熟的实现。一个稍微好一点的方法是首先将其作为一个接口:

    public interface IArticleFactory
    {
        IArticle CreateArticle(string sku);
    }
    

    public class MyArticleFactory
    {
        private Dictionary<string, Func<IArticle>> instantiators =
            new Dictionary<string, Func<Iarticle>>();
    
        public MyArticleFactory()
        {
            Register("Jeans", () => new Jeans());
            Register("Shirt", () => new Shirt());
            // etc.
        }
    
        public IArticle CreateArticle(string sku)
        {
            Func<IArticle> instantiator;
            if (creators.TryGetValue(sku, out instantiator))
                return instantiator();
            throw new UnknownSkuException(sku);
        }
    
        protected void Register(string sku, Func<IArticle> instantiator)
        {
            creators.Add(sku, instantiator);
        }
    }
    

    几个重要的区别:

    • 注册不是公开的,也不应该公开。注册通常位于某个配置文件中,或者是私有的。

    • 不需要 IArticle

    • 对重复注册引发异常。我不喜欢简单地返回的想法 false ; 如果您尝试两次注册同一工厂方法,则应将其视为错误。

    • 它不是静态的。您可以用其他工厂替换此工厂。您可以对其进行单元测试。

    当然,更好的方法是使用现有的无数.NET依赖注入/反转控制框架,例如 Ninject AutoFac .

        2
  •  2
  •   Marc Gravell    16 年前

    我不知道它是否有这样的“名称”,但它看起来像某种手动服务解析器。我能看到的问题(遗憾的是,从经验来看)是,它实际上是不灵活的,因为:

    • 注册只有一个配置
    • 很难进行单元测试

    顺便说一句,可能更容易:

    return Activator.CreateInstance(articleRegistry[sku]);
    
        3
  •  1
  •   BFree    16 年前

    我认为你在这里所做的基本上是依赖注入(或者说控制反转就是酷孩子们所说的)。请查看以下链接:

    维基百科的解释: http://en.wikipedia.org/wiki/Dependency_Injection

    两个DI.Net框架:

    http://structuremap.sourceforge.net/QuickStart.htm

    http://www.castleproject.org/container/index.html

        4
  •  0
  •   dsimcha    16 年前