当对象仅使用部分接口时,如何构造接口?


9

我有一个项目,其中有两个类都需要更新同一张表的数据库访问对象。框架和项目的约束使得它无法合并这两个类。我在下面创建了一个案例,展示了如何进行设置。A类需要能够更新和读取记录,而B类需要能够更新和删除记录。

如果我按原样使用这些类,则可以正常工作,但是我对每个类都需要不使用它的功能这一事实感到怀疑。例如,为了使用类A,我必须将实现删除功能的dao传递给它,即使它永远不会被调用。同样,我必须将实现read函数的dao传递给B类,但它永远不会被调用。

我考虑过通过继承其他接口(IReadDao,IUpdateDao,IDeleteDao是将要继承的dao)来实现该方法,但是这种方法对于每种功能组合(IUpdateAndRead,IReadAndDelete,IReadAndUpdate ... )

我想为dao使用接口,因为我不想将应用程序与数据库耦合。有没有一种模式或方法可以实现任何人都知道的我想要的东西?提前致谢。

class IDao {

  void update(ModelDao model);
  void delete(String guid);
  ModelDao read(String guid);

}

Class A {

  private IDao dao;

  public A(IDao dao) {

    this.dao = dao;

  }

  public void doStuff() {

    ModelDao model = new ModelDao();

    ...

    dao.update(model);

  }

  public void readThenDoSomething(String id) {

    ModelDao model = dao.read(id);

    ...

  }

}

Class B {

  private IDao dao;

  public B(IDao dao) {

    this.dao = dao;

  }

  public void makeUpdate() {

    ModelDao model = new ModelDao();

    ...

    dao.update(model);

  }

  public void delete(String id) {

    dao.delete(id);

  }

}

2
为什么每个组合都需要单独的接口,而不是仅让使用它们的类实现所需的接口?
— yitzih

在上述情况下,我不必将IDao传递给A的构造函数,而必须传递一个实现IUpdate和IRead的对象,那么实例变量“ dao”的类型将是什么?不必一定是IUpdateAndReadDao之类的东西吗?它仍然需要是一个接口,因为如果我告诉它采用特定于数据库的实现,那么我已经将该类耦合到了db。那是你在问什么吗?
— jteezy14

3
我认为这是接口隔离原理(Ifrom SOLID)的完美示例。可能想读一点。
— 克里斯托弗·弗朗西斯科

Answers:


10

根据克里斯托弗(Christopher)的评论,隔离接口可能会更好一些。所以,你至少需要IReadDao,IDeleteDao和IUpdateDao。请注意,您不一定需要三个类。如果可以用这种方式组合代码库,则可以拥有一个实现所有三个接口的大型DAO类。

为了避免组合爆炸(例如以避免对需要IReadUpdate,IDeleteUpdate等接口),则可以提供单独的接口中构造子注入(可以通过相同的对象两倍不同的参数),或提供一个单一的对象支持两个或更多个接口在使用的通用方法调用中extends。

构造函数注入:

class MyDaoLibrary : IUpdateDao, IInsertDao, IDeleteDao {
    //Etc....
}

class A
{
    //It is OK if the IoC container factory provides the same instance for both parameters.
    a(IUpdateDao dao1, IDeleteDao dao2) {
        this.updater = dao1;
        this.deleter = dao2;
    }
    //Etc....
}

setter注入,使用通用方法:

<T extends IUpdateDao & IDeleteDao> void InitializeDao(T dao)  //Pass a single object that implements both IUpdateDao and IDeleteDao

使用setter注入时,如何声明在InitializeDao函数中设置的实例变量?
— jteezy14

您将需要两个实例变量(一个用于删除,一个用于更新)...分配dao给两个。
— 吴敬Wu

哦,是的,这很有道理。非常感谢您的出色回答!
— jteezy14
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.