与接口,工厂和控制反转混淆

mik*_*igs 3 factory dependency-injection interface inversion-of-control

使用接口是一种非常简单的方法来删除依赖项,但是当您的某个类需要一个未由接口定义的方法时会发生什么?如果您正在使用构造函数注入或工厂,那么如何在不进行转换的情况下访问该额外方法?这可能吗?

这是一个有这个问题的工厂的例子.我想做一些不可能的事吗?谢谢你的帮助.

interface IFoo {
    int X { get; set; }
    int Y { get; set; }
}

public class A : IFoo {
    int X { get; set; }
    int Y { get; set; }
}

public class B : IFoo {
    int X { get; set; }
    int Y { get; set; }
    int Z { get; set; }
}

public static class FooFactory {
    public static IFoo GetFoo(string AorB) {
        IFoo result = null;
        switch (AorB) {
            case "A":
                result = new A();
                break;
            case "B":
                result = new B();
                break;
        }
        return result;
    }
}

public class FooContainer {
    private IFoo foo;

    public FooContainer(IFoo foo) {
        this.foo = foo;
    }

    /* What methods would you define here. I'm new to IoC. */
}

public class Main(...) {
    int x,y,z;
    IFoo fooA = FooFactory.GetFoo("A");
    x = foo.X;
    y = foo.Y;

    IFoo fooB = FooFactory.GetFoo("B");
    x = foo.X;
    y = foo.Y;
    z = foo.Z; /* Does not compile */
    z = ((B)foo).Z; /* Compiles, but adds unwanted dependency */
}
Run Code Online (Sandbox Code Playgroud)

Pat*_*her 6

你确实需要施展.这是正常的,有时是必要的.这通常表明某些事情是错误的.

理想情况是,如果方法/例程接受/返回接口,那么您的逻辑只关心该接口公开的成员.如果在该方法内部,您发现自己正在检查确切的类型,以便您可以转换为该类型并根据类型调用不同的成员,那么可能是错误的.

假设您有一个IContact接口,并且您实现此功能的一些实体是您的类Customer,PurchaserContractor.如果你有一个采用IContact 的SendChristmasCard方法,它应该只关心IContact成员.如果你在这个方法中有逻辑正在做一个选择案例,obj.GetType().ToString以找出它是否是一个客户,那么:

  1. 该功能可能应该在代码库的Customer -centric方面结束,将Customer对象作为参数.(在你的例子中,对于A类和B类有不同的逻辑.)
  2. IContact应该定义SendChristmasCard方法将调用的公共成员,并且完全不知道特定对象内部的逻辑.实现IContact的每个类都将以不同方式实现这些成员.(在你的例子中,A类也会实现属性B,但它不会对它做任何事情.)

在方法返回一个接口而你使用该对象的情况下,上面仍然适用,但根据我的经验,它可以,现在和时,最好忍受铸造.通过"修复"情况添加的复杂功能可能会使其更加复杂.我会说逻辑的进一步向上和非标准,只是采取简单的方法. SendChristmasCard显然不是核心功能; 如果一个IContact工厂方法只是方便的方法给你所有的联系人,那么可能只是使用它,将它传递给SendChristmassCard(IContact联系人),并在里面检查类型说"这是很好的购买你今年"或者"这对你来说今年很受欢迎"等等.但如果这是你系统中的核心逻辑,你真的需要寻找更好的方法.

看看装饰模式,这可以帮助在这种情况下.