我试图说服一位同事,一个函数应该将接口作为参数,而不是对象本身。我认为小对象可以很好地传递,但是对于大对象,我会给它们一个接口,只是传递i / f,而不是整个。
请注意,只会出现其中一个大类 - i / f永远不会用于其他对象。这仅仅是为了隐藏对象的实现。
您是否同意将大型课程分成界面是一种很好的做法? 这样做有什么不利之处吗?
示例:
public interface class IVeryLargeClass
{
void DoSomething();
...
};
public ref class VeryLargeClass : public IVeryLargeClass
{
public:
virtual void DoSomething() { ... }
...
};
public ref class AnotherClass
{
public:
AnotherClass(VeryLargeClass^ vlc) { vlc->DoSomething(); }
// OR
AnotherClass(IVeryLargeClass^ vlc) { vlc->DoSomething(); }
};
答案 0 :(得分:12)
您在面向对象开发中学到的第一个原则之一:
编程到界面,而不是 实施
你指出“只有这些大类中的一个 - i / f永远不会用于不同的对象”。在你的情况下这可能是真的,但我希望每次这样的陈述都是错误的时候我都有镍。
除了考虑是否可能有多个接口实现之外,还应考虑具体对象是否导出(或可能导出)与接口中声明的操作不共享逻辑关联的其他方法。在这种情况下,您可以简单地在一个或多个附加接口中声明其他操作。然后,客户端只需要与导出其感兴趣的操作的接口耦合。
简而言之,接口提供了一种管理客户端和提供者之间耦合的方法。
答案 1 :(得分:7)
Dependency Inversion Principle可以概括为:最好依赖于抽象而不是结核。
传递接口几乎总是比通过具体类更好。
也就是说,在特定模块中,对内部类型的高凝聚力是可以的,但是对于何时以及如何传递具体对象,这是非常主观的。
答案 2 :(得分:3)
如果你传递一个实现,你就会失去使用接口的一个优点,这意味着将逻辑与实际实现分开。
软件模块A的界面 故意与...分开 该模块的实施。该 后者包含了实际的代码 中描述的程序和方法 界面,以及其他 “私人”变量,程序等。 任何其他软件模块B(可以 被称为A)的客户 与A的交互被迫这样做 只能通过界面。一 这个的实际优势 安排是取代 另一个实施A. 符合相同规格的 界面不应该导致B到 失败 - 只要它的使用符合 与规格 界面(另见Liskov 替代原则)。
答案 3 :(得分:3)
为了创建界面,我宁愿避免创建和界面。如果你可以在多个地方使用该界面,那么你就有了胜利者 - 或者如果这是一个公共功能和类,你特别希望简化。
答案 4 :(得分:1)
另一个问题是你的大班本身。这可能不在你正在做的范围内,但是一个非常大的类意味着它可能在一开始就做得太多了。你可以将它重构为较小的classess,你所调用的函数中所需的信息是否封装在它自己较小的类中?如果您创建一个针对该类的接口,您可能会发现它比您当前拥有的非常大的类更具可重用性。