引用具体类作为参数的接口方法会导致耦合吗?

时间:2014-04-14 11:07:52

标签: java interface coupling loose-coupling concrete

我在考虑编程接口而不是具体的类,但我有一个疑问:是否任何接口方法都能够保存对具体类的引用?

假设以下情况:

1)

public interface AbsType1 {
    public boolean method1(int a); // it's ok, only primitive types here
}

2)

public interface AbsType2 {
    public boolean method2(MyClass a); // I think I have some coupling here
}

我应该在这里选择不同的设计以避免后者吗? e.g。

public interface MyInterface {} // yes, this is empty

public classe MyClass implements MyInterface {
    // basically identical to the previous "MyClass"
}


public interface AbsType2 {
    public boolean method2(MyInterface a); // this is better (as long as the
                                           // interface is really stable)
}

但仍有一些东西不能说服我......虽然我看到其他人这样做,但我觉得对于宣布一个空接口感到不舒服。 也许和抽象类在这里会更好用吗?

我有点困惑。

修改

好的,我会通过举个例子来尝试更具体。假设我正在设计ShopCart,我当然希望在购物车中添加商品:

public interface ShopCart {
    public void addArticle(Article a);
}

现在,如果文章是一个具体的类,如果它的实现随着时间的推移而变化怎么办?这就是为什么我可以想到把它变成一个接口,但是再一次,它可能不适合至少在语义层面,因为接口应该指定行为而文章没有(或几乎没有......)我猜它是一种实体类)。

所以,我现在可能最终得出的结论是,在这种情况下将文章作为抽象类是最好的......你怎么看待它?

3 个答案:

答案 0 :(得分:2)

我会使用接口,因为组合比继承好得多。 “任何接口方法都应该能够保存对具体类的引用吗?”,为什么它不应该?包中的某些类是耦合的,这是事实和常用技术。当您在界面中标记此关系时,您会看到哪些类依赖于您的实现。依赖关系或组合关系不是继承,所以我会避免抽象类。

答案 1 :(得分:1)

在我看来,Interfaces对于实施可能不同的所有类型都适用。但是如果你定义了一个引入新类型的module,那么它并不打算有替代实现,那么首先不需要将它定义为Interface。在我看来,这通常会过度设计。它取决于问题领域,通常在支持测试或AOP编织的方式上。

例如,考虑一个2D问题域,您需要将Location建模为一种类型。如果Location始终由xy坐标表示,则可以将其作为Class提供。但是,如果您不知道Location可能具有哪些属性(GPS数据,x,y,z坐标等),但您依赖某些行为,例如distance(),则应将其建模为接口代替。

答案 2 :(得分:1)

如果AbsType中没有MyClass可以访问的公共方法,那么空接口可能不是一个好方法。

静态方法没有接口声明(契约),否则可能在这里有意义。

因此,如果AbsType不会使用MyClass / MyInterface中的任何方法,那么我认为它基本上只是为了其他目的而存储类对象。在这种情况下,请考虑使用泛型来明确您希望如何使用AbsType而不与客户端代码紧密耦合,例如

public class AbsType3<C extends Class<?>> {

  public boolean method3(T classType) {...}

}

然后,如果需要,可以通过将<C extends Class<?>>类型参数替换为可能也是接口的其他内容来限制类的类型,例如 <C extends Class<Collection<?>>>

空接口有点像类的布尔标志:一个类实现接口(true)或不实现(false)。如果有的话,应该使用这些标记接口来传达关于如何使用(或不使用)类的重要声明,例如,请参阅Serializable