什么是不透明依赖项?

时间:2016-09-21 22:37:54

标签: design-patterns anti-patterns

我正在阅读有关设计模式的内容,并且我注意到术语"不透明依赖项" 已被广泛使用。 一些消息来源表示:

  

不透明的依赖关系是一种糟糕的依赖关系

     

不透明依赖项是您无法使用类分配的类型   公共API。

但我对此并不了解。

有人可以给我一些使用这种依赖关系的例子,为什么要避免使用它们?

3 个答案:

答案 0 :(得分:2)

例如:

public class MyService
{
    private IRepository repo = new Repository();

    public MyService()
    {
        repo = new Repository();
    }
} 

repo将被归类为不透明依赖,因为没有(简单)方法可以改变它,例如在单元测试中。

这是相同的示例,但是作为透明依赖

public class MyService
{
    private IRepository repo = new Repository();

    public MyService(IRepository repositoryDependency)
    {
        repo = repositoryDependency;
    }
} 

在这里,我们可以传入我们自己的IRepository并测试MyService的行为,而像DI Container这样的工具可以为我们设置我们的依赖关系,它不能在Opaque中示例

答案 1 :(得分:2)

不透明依赖项是隐藏的依赖项。与不透明依赖相反的是显式依赖。

不透明的依赖关系很糟糕,因为使用类的开发人员可能没有意识到存在这种依赖关系。当他们调用各种方法时可能会出现意想不到的副作用。

不透明依赖

public class Users
{
    private Database database;

    public Users()
    {
        this.database = new SqlDatabase(...);
    }

    public User Find(int userId)
    {
        return database.GetById(...);
    }
}

显式依赖

public class Users
{
    private Database database;

    public Users(Database database)
    {
        this.database = database;
    }

    public User Find(int userId)
    {
        return database.GetById(...);
    }
}

答案 2 :(得分:1)

在@NikolaiDante的答案的基础上,我想补充一个论点,即不透明的依赖关系可以通过透明的方式引入。

例如:

public class MyService
{
    private ISomeContext context;

    public MyService(ISomeContext context)
    {
        this.context = context;
    }

    public void DoSomethingUseful()
    {
        var repository = this.context.CreateRepository<IRepository>();

        repository.Save(new X());
    }
}

虽然对ISomeContext的依赖是透明的,但它隐藏了它用于解析IRepository的事实,我现在认为它是一个不透明的依赖。恕我直言,这降低了班级设计的“纯度”,往往有利于方便或懒惰。

“挖掘合作者”部分here中有关于此类问题的更多信息。