-1

这是一个通用的设计问题。我们经常使用接口来解耦组件,写入接口而不是实现等。有时接口使用基本的注入技术,例如,

interface IMyInterface
{
    void DoSomething();
}

static class IMyInterfaceFactory
{
    public static IMyInterface GetInstance()
    {
        return new MyInterfaceInstance();
    }
}

class IMyInterfaceConsumer
{
    IMyInterface mInterface;

    public IMyInterfaceConsumer()
    {
        this.mInterface = IMyInterfaceFactory.GetInstance();
    }

    public void UseTheInterface()
    {
        this.mInterface.DoSomething();
    }
}

我的问题是关于使用 var 关键字。甚至不使用真正的 C# 接口,但仍然在设计意义上创建一个“接口”,

static class IMyInterfaceFactory
{
    // of course, this doesnt need to be a single instance
    static MyInterfaceInstance mSingleInstance; 

    // no longer programming to the interface, just returning the instance
    public static MyInterfaceInstance GetInstance()
    {
        // null coalesce
        return mSingleInstance ?? (mSingleInstance = new MyInterfaceInstance());
    }
}

class IMyInterfaceConsumer
{
    public void UseTheInterface()
    {
        // shorthand way, could also omit var, too 
        var myInterface = IMyInterfaceFactory.GetInstance();
        myInterface.DoSomething();
    }
}

这样我仍然只需要更改一次工厂,只要它返回的任何实例支持需要使用的方法,它就可以工作。然而,优点是生产和消费对象甚至不需要知道任何显式接口,不存在。它还可以干净地支持具有多个方法的接口(防止臃肿的接口声明)。

一个明显的缺点是,每次您想从“接口”使用方法时,工厂可能必须重新实例化该类,除非缓存了单个实例(如上)或使用了一些记忆技术。

这种方法的优点/缺点?这是一种常见的做法吗?

4

2 回答 2

5

var关键字没有什么动态或松散的。它在编译时触发静态类型推断。

您的第二段代码的行为与

public void UseTheInterface()
{
    // shorthand way, could also omit var, too 
    MyInterfaceInstance myInterface = IMyInterfaceFactory.GetInstance();
    myInterface.DoSomething();
}

工厂函数仍然是强类型的。事实上,通过删除接口,您使消费者代码的耦合更加紧密。

于 2012-09-19T21:08:47.437 回答
1

Var 关键字在技术上仍然是强类型的,因此您的代码确实知道它是什么类/接口。如果您打算将其转储到一个对象中,那么我们是说您的其余代码不知道该工厂的内容是什么。我不建议这样做,因为这会导致您强制转换该对象以利用其中的任何内容。

我不确定您要尝试使用“防止臃肿的接口声明”,但您也可以通过扩展基类或抽象类来实现多态性。这样一来,子类之间的任何通用代码都可以单独保留,并且每个子类的任何特定代码(方法或属性)都可以被覆盖。

如果您希望一起更改接口,则需要在接口中实现接口,请参阅这篇文章。所以你基本上只有接口 A 只有方法 DoStuff() 和从这个接口继承的其他接口可以像你描述的那样多态地使用。

interface A
{

DoStuff();
}

interface B : A
{
DoSomethingElse();
}

class C : B
{

DoStuff(){}
DoSomethingElse(){}
}

顺便说一句,您上面的“单实例缓存”代码接近于所谓的单例模式

于 2012-09-19T21:17:27.507 回答