创建接口和/或抽象类是多此一举





5.00/5 (3投票s)
这是一篇简短的技巧文章,其中包含了我关于为什么我们不应该为应用程序中的每一个类都盲目创建接口和/或抽象类的想法。
引言
这是一篇简短的技巧文章,其中包含了我关于为什么我们不应该为应用程序中的每一个类都盲目创建接口和/或抽象类的想法。这些更多是想法,可能有些人不同意我的观点,但这里的目的是与他人分享我的看法,以便他人可以分享他们的想法,让我/我们从中学习。
背景
前几天,我和别人讨论时,我建议将第三方库的调用抽象到一个类中,这样调用应用程序就可以只依赖于这个类。这样做的理由是,有一个单一的点在与第三方库通信,而不是将对该库的调用分散在应用程序代码的各个地方。将来,如果我们决定使用另一个第三方库,只需要更改这个类的内部实现,而调用者将不受影响。
这个解决方案的设计方式是,新的实现包含一个接口,一个实现该接口的抽象类,以及一个包含实际库调用的具体类。现在,在正常情况下,我会说这是一个优雅的解决方案,因为我们遵循了依赖倒置原则,并使用了适当的接口。但这一次,我开始思考我们是否真的需要接口和抽象类。
我完全赞成使用接口、抽象类和依赖倒置原则。请阅读以下文章,了解我对它们的看法:
但有时,创建接口和抽象类可能是多此一举。让我们看看为什么。
为什么我们需要接口
接口主要是用来定义一个契约。调用者可以使用接口,并通过让具体实现被注入,或者使用工厂或服务定位器来选择任何符合该契约的具体实现。重要的是要理解,“调用者可以选择”是这里的真正意义。现在想象一个验证电子邮件格式的场景。调用者是否会有需要选择性地选择一个提供此功能的类的场景?如果这个问题的答案是“否”,那么为什么我们需要接口?调用者为什么不能直接使用这个类?
那么,如何决定是否应该创建接口呢?答案是,当我们想定义一个可以被多个具体类满足的契约,并且这些多个具体类可以在应用程序中共存,并且调用者会根据某些条件选择性地调用它们时。如果我们遇到的情况是,不可能在应用程序中共存多个具体的实现,那么也许创建接口是不需要的,如果创建了,那将是多此一举。
关键在于,我们不应该为了创建接口而为每个类都创建接口。应该有一个合理的理由来创建接口。此外,在选择创建接口时,应考虑可扩展性和灵活性。但如果我们相当确定我们不需要强制执行契约,并且不可能让多个具体的实现共存,那么我们可能根本不应该创建接口,而是直接使用具体类。
为什么以及何时需要抽象类
首先,抽象和abstract
类是不同的东西。抽象是类向其调用者提供的功能,而abstract
类是语言构造。这里的问题是,我们应该何时创建abstract
类。答案应该是——每当我们有可能共存多个具体的实现,并且这些具体的实现需要一些默认和/或共同的行为时,我们就应该创建一个abstract
类,并将这些默认/共同的行为放在这个abstract
类中。这个abstract
类现在将实现我们的接口,而具体类将继承自这个abstract
类。
关注点
使用面向对象的原则和实践对于创建优秀软件至关重要。但我们首先应该理解这些实践存在的理由以及这些模式试图解决什么问题。然后,我们才应该开始在我们的应用程序中使用它们。否则,如果我们开始使用这些实践,而甚至没有需求,那么最终的设计/代码可能会是多此一举。
我们应该记住 KISS(保持简单,愚蠢)原则,同时分析应用程序的需求,然后开始相应地设计我们的解决方案。这不仅适用于接口和抽象类,也适用于设计和架构模式。我们不应该仅仅为了使用模式而将它们包含在设计中,而应该有合理的必要性,然后才使用它们。
本文是从初学者的角度撰写的。希望对您有所帮助。
历史
- 2016年10月13日:初稿