【问题标题】:Could I use the Factory Pattern in this scenario?我可以在这种情况下使用工厂模式吗?
【发布时间】:2011-04-20 03:46:04
【问题描述】:

我想知道我是否可以 - 以及如何 - 我可以在这种情况下使用工厂模式吗?

我有以下课程...

public interface IStub<T> where T : class
{
    IEnumerable<T> CreateStubs();
}

public FooStub : IStub<Foo>
{
    public IEnumerable<Foo> CreateStubs() { ... }
}


public BarStub : IStub<Bar>
{
    public IEnumerable<Bar> CreateStubs() { ... }
}

..等等...

我想知道是否可以通过像...这样的工厂方法创建实例

// This ends up returning an enumerable of Stubs.
var stubs = StubsFactory.CreateStubs<Foo>(); 

这可能吗/我在正确的轨道上吗?

【问题讨论】:

  • 它是测试存根还是您要创建的其他任何东西?因为你有多个相同类型的存根,它是什么样的存根。

标签: .net design-patterns factory-pattern


【解决方案1】:

像这样。如果实现和存根不在同一个程序集或命名空间中,请修改 Type.GetType 行。

class UberCoolFactory
{
      public static T CreateStubs<T>()  
      {
          string ns = typeof(T).Namespace;
          string name = typeof(T).Name;
          string assembly = typeof(T).Assembly.GetName().Name;
          Type type = Type.GetType(string.Format("{0}.{1}Stub, {2}", ns, name, assembly));
          return (T)Activator.CreateInstance(type);
      }
 }

替代方案:

 class FactoryTwo
 {
    /// <summary>
    /// Search through all loaded assemblies that exists in the current directory.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public static T CreateStub<T>() where T : class
    {
        string currentDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        string wantedTypeName = typeof(T).Name + "Stub";

        List<Type> foundTypes = new List<Type>();
        foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
        {
            if (!currentDir.Equals(Path.GetDirectoryName(assembly.Location)))
                continue;

            foreach (var type in assembly.GetTypes())
            {
                if (!type.Name.Equals(wantedTypeName))
                    continue;

                foundTypes.Add(type);
            }
        }


        if (!foundTypes.Any())
            return null;
        if (foundTypes.Count > 2)
            throw new AmbiguousMatchException("Found multiple stubs implementing '" + typeof(T).FullName + "'.");

        return (T) Activator.CreateInstance(foundTypes[0]);
    }
}

用法:

var instance = UberCoolFactory.CreateStubs<Foo>();
var instance2 = FactoryTwo.CreateStub<Foo>();

【讨论】:

  • @jgauffin :这是一个构造函数类?什么?一个工厂?我认为工厂方法通常是静态的..... ???
  • 构造函数什么时候可以返回值?它可以是静态方法、虚拟方法或任何您喜欢的方法。你的想象力(或知识)是极限。我已经更新了示例以将它们包装在类中并使它们成为静态的。
  • 是的。我编辑了很多代码。先误读你的问题。
  • 我认为按字符串搜索类型,特别是在自己的程序集中,是个坏主意。这仅在字符串来自配置文件时才可接受 - 即您正在配置某些内部或外部配置动态使用的类型
  • 为什么在我的示例中这是一个坏主意?你在说什么字符串?存根通常是测试时使用的虚假实现。
【解决方案2】:

扩展 jgauffin 关于搜索目标类型的答案:

string targetType = "BlahStub";
IEnumerable<Type> result = 
        from assembly in AppDomain.CurrentDomain.GetAssemblies()
        where !String.Equals(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), assembly.Location, StringComparison.OrdinalIgnoreCase)
        from type in assembly.GetTypes()
        where String.Equals(type.Name, targetType, StringComparison.OrdinalIgnoreCase)
        select type;

【讨论】:

    【解决方案3】:

    工厂声明:

    static class StubsFactory<TStub, TClass>
                where TStub : IStub<TClass>
                where TClass : class
    {
        public static IEnumerable<TClass> CreateStubs()
        {
            return ((TStub)Activator.CreateInstance<TStub>()).CreateStubs();
        }
    }
    

    用法:

    IEnumerable<Foo> q = StubsFactory<FooStub, Foo>.CreateStubs();
    

    这是你要找的吗?

    【讨论】:

    • 这段代码只是“new FooStub().CreateStubs()”的替代品。
    • @jgauffin:不,因为您只需要指定一个类型,根本不需要指定实例
    • 是的,但是你创建了指定的类型。因此它只是替换 new FooStub().CreateStubs()。
    • @jgauffin:据我了解,OP 需要拨打IStub.CreateStubs() 还是不拨打?如果他只需要找到Some : IStub(可能根本是一个接口)而不是通过接口调用 - 你的代码更合适。
    • 我理解是因为他想创建工厂类并举了两个不同的例子,而不是必须使用它们。
    猜你喜欢
    • 2012-03-28
    • 2016-09-12
    • 2016-11-07
    • 2022-08-05
    • 2018-05-05
    • 1970-01-01
    • 2022-11-14
    • 1970-01-01
    • 2012-09-09
    相关资源
    最近更新 更多