首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >抽象工厂实验

抽象工厂实验
EN

Code Review用户
提问于 2014-02-06 03:57:56
回答 2查看 232关注 0票数 6

虽然我应该通过尼尼特或类似的项目使用依赖注入,但我一直试图实现一个抽象工厂设计,它将为我提供以下易于阅读和使用的语法:

代码语言:javascript
复制
UniversalFactory.Factory<IFoo>.Create<FooImpl>(... parameters ...);

我把这个实验放在这里是为了征求一些建设性的反馈,包括实现逻辑和设计推理。

以下是我目前的实现:

代码语言:javascript
复制
public class UniversalFactory
{
    private readonly IFactory<IFoo> FooFactoryEx;

    public UniversalFactory()
    {
        FooFactoryEx = new FooFactory();
    }

    public IFactory<T> Factory<T>()
    {
        if (typeof (T) == typeof (IFoo))
            return (IFactory<T>)FooFactoryEx;
        return null;
    }
}

public interface IFactory<in TF>
{
    T Create<T>(params object[] p) where T : TF;
}

public class FooFactory : IFactory<IFoo>
{
    public T Create<T>(params object[] p) where T : IFoo
    {
        if (typeof(T) == typeof(FooImpl))
        {
            var id = Convert.ToInt32(p[0]);
            return (T)FooImpl.Create(id);
        }
        return default(T);
    }
}

public interface IFoo
{
    // Some interface
}

public class FooImpl : IFoo
{
    public int Id { get; set; }

    private FooImpl(int id)
    {
        Id = id;
    }

    public static IFoo Create(int id)
    {
        var foo =  new FooImpl(id);
        return foo;
    }
}

此代码允许实例化UniversalFactory并成功调用以下内容:

代码语言:javascript
复制
UniversalFactory.Factory<IFoo>().Create<FooImpl>(1);

我对这一做法的推理是:

  1. 通过调用UniversalFactory,可以很容易地识别所有结构。
  2. 根据正在构建的接口实现调用工厂,从新的对象请求中隐藏有关特定工厂的所有详细信息。
  3. 在请求中可以清楚地识别对象类型及其构造参数。
  4. 对象构造保留在每个类中,在构造时对其他对象的任何其他更新都可以在工厂方法中进行。

我目前的实现(至少)存在以下缺陷:

  1. 没有确保IFoo由IFactory实现的编译时安全性。只确保FooImpl实现了IFoo。
  2. UniversalFactory.Factory必须为工厂支持的每个接口添加一个检查。
  3. 单个工厂必须在每个类中调用静态Create()方法。如果静态创建可以以通用方式调用,并以某种方式将Create(params object[] p)映射为Create(int,string b,.)会更好。如有需要。

有什么想法?反馈?这种方法是不必要的还是过于复杂的?希望这个实验至少能引起一些其他人的兴趣。

EN

回答 2

Code Review用户

发布于 2014-02-06 05:42:14

严格地说,你要做的不是抽象的工厂。对于抽象工厂,用例应该如下所示:

代码语言:javascript
复制
UniversalFactory.Factory<IFoo>  // client has no idea about IFactory<IFoo> implementation
                .Create(... parameters ...); // client has no idea about IFoo implementation, returns IFoo

理想情况下,您甚至不需要传递参数。这就是你毕竟在建厂的原因。若要委派对象创建,请执行以下操作。

其他次要评论:

  1. where T : TF --这些不是泛型参数的描述性名称。也许你能想出更好的名字。
  2. var id = Convert.ToInt32(p[0]); -我不确定我喜欢这里的Convert。它可能会隐藏错误和误用。我认为在这种情况下,坚强的演员会更好。
  3. public static IFoo Create(int id) -我不认为有任何理由使用工厂方法。公共类FooImpl : IFoo { public int { get;私有集;} public FooImpl(int id) { Id = id;}这看起来要干净得多。另外,我认为Id策划人应该永远是私密的。

总的来说,我认为除非您是出于学习目的,否则您应该只获取一个现有的DI库,就像您自己已经讨论过的那样:)

票数 2
EN

Code Review用户

发布于 2014-02-06 09:40:41

代码编写得很好,但给出一个类是很有力量的。它在本质上造成了依赖瓶颈。

工厂的大部分优点是能够交换/更改/更新实现,而不需要额外的重新编译或更改。

尽管在这里,您正在调用Universal (如果不重新编译使用它的每个类,它作为实现是无法更改的)

其次,在调用本身中调用直接实现。这意味着你也依赖于这一点。

您正确地断言正确的方法可能是DI系统。或者,你可以留在工厂里,做一些类似的事情。

代码语言:javascript
复制
IGlobalFactory factory;//Possibly constructor initialized

IFoo bar = factory.Create<IFoo>();

通过该方法注入GlobalFactoryImpl并向工厂提供IFoo的实现。

让您的主类知道存在一个FooImpl通常是个坏主意,这样,GlobalFactoryImpl可以在调用时返回FooImpl,但是GlobalFooBlargFactoryImpl可以返回FooBlargImpl,您仍然可以交换实现,但是一切都有点模糊。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/41030

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档