你应该总是Code to Interfaces in Java
我了解编码到接口的原理 – 将接口的实现与接口分离,并允许交换接口的实现。
我应该编写接口为我写的每个类或是过度杀伤 ? 除非真的值得,否则我不想将项目中源文件的数量加倍。
我可以使用什么因素来决定是否通过接口进行编码?
一般来说,我同意其他答案:当你知道或预期变化和/或不同的实现,或者为了可testing性,使用一个接口。
但事先并不总是很容易知道未来会发生什么变化,特别是如果你不是那么有经验的话。 我认为这个问题的解决scheme是重构:保持简单(=无界面),只要不需要。 当需要时,只需做一个“介绍/提取接口”重构(几乎所有体面的IDE支持)。
当你这样做时,只提取调用者实际需要的那些方法。 不要害怕抽取更多的一个单独的接口(如果不是所有提取的方法真的是一致的)。
重构的一个驱动因素可能是testing:如果你不能轻易地用类来testing,只考虑引入一个/一些接口。 这也可以让你使用嘲笑,这在很多情况下可以大大简化testing。
编辑:根据塔斯基的评论,我已经意识到一个更重要的情况/调整到以前的陈述:
如果你提供了一个外部的API(对于其他的子项目,或者真的把它释放),那么在API中使用接口(除了简单的值类)几乎总是一个好主意。
它可以让你改变impl如果你喜欢,而不打扰客户端代码。 只有在您还必须更改界面时,您才会遇到问题。 不破坏兼容性将是非常棘手的(如果不是不可能的话)。
我至less在以下一种情况下使用它:
1)我想解耦不相关的模块/类彼此,我希望它被反映的Java包依赖项。
2)当依靠构build依赖时,解耦是很重要的
3)当实现可能通过configuration或在运行时dynamic更改(通常由于某种devise模式)
4)当我想要一个类是可testing的,我把它的“链接点”放到外部资源接口上,这样我就可以使用模拟实现。
5)较less见:当我想要一个选项来限制对某个类的访问。 在这种情况下,我的方法返回一个接口,而不是实际的类,所以调用者知道我不希望他对返回的值做其他操作。
不,每个class级都不应该有一个界面。 这是过火平方。
当您需要从完成的过程中抽象出所做的事情时,您可以使用一个接口,并确定实现可以改变。
看看java.util Collections API是一个很好的例子。 List接口是List的一般思想的一个很好的抽象,但是你可以看到有很多方法来实现它:ArrayList,LinkedList等
更新:那么你怎么devise一个具体的类,你有客户需要一个接口后决定,然后通过添加一个接口来打破你的客户? 是的,就是这样。 你怎么知道你不知道? 没有软件或方法可以解决这个问题。
对你来说好消息是,从具体类中提取接口对于你和你的客户来说都是一件容易的重构。 IDE经常处理这种事情。 你和你的客户应该利用他们。
我会说层,像服务和持久性,应该总是有接口。 任何可以代理的东西都应该有一个接口。 如果你正在做Spring AOP,那么你想用一个方面来装饰的东西应该有一个接口。
模型或值对象,如Person或Address或Phone,不应该有一个接口。 一个不可变的值对象不应该有一个接口。
其余的陷入灰色地带。 使用你最好的判断。
长话短说,没有。 你是应用程序的创造者,所以你有一个体面的想法可以改变。 一些devise模式的书籍在我看来有点疯狂,因为他们似乎总是将devise推向界面,而不pipe实现。 有时候,这只是矫枉过正。 对于我最新的应用程序(小尺寸),我有一个数据库接口,因为我认为有机会我可能稍后将它移植到networking并切换到MySQL。 当然实际上,从现有的类中创build一个数据库接口很容易,稍后添加一个“implements myDbInterface”,稍加修改即可。 这是有效的,因为我是唯一的开发者。 在一个更大的团队或不同types的产品上,这可能是一个不同的答案。 只要使用你最好的判断(当然读了所有好的答案)。
我喜欢想象一个人使用接口时,可插拔性和不同行为的潜力是重要的。 服务是完美的契合。 有人可能想要一个默认的实现,但伪造(嘲笑)等是另一个。 这显然意味着应该有一个intf,因为总会有至less两种forms。
另一方面,价值types应该是最终的类别。 他们不应该延长。 值types包括Suburb,MimeType等。 如果有这些使用组成的变化。 作为一个目标,我尝试和把小行为,如果在我的价值types。 validation它的简单types包装等可能是最复杂的事情。 例如,需要r / g / b的Color类应该validation每个组件是否在0到255之间,这就是它。
当你期望一个行为改变时,可以使用界面。 。 在未来。
或者你的class级可以清楚地处理变化。
例如。
public static void main(String s[]) { Employee e1=new Employee(new Salesman()); Employee e2=new Employee(new Manager()); system.out.println(e1.performaction()); system.out.println(e1.performaction()); } Class Employee { //which changes frequently Authority a; public Employee(Authority a) { this.a=a; } public String performAction() { a.action(); } }
// ———————————————— ——————
interface Authority { public String action(); } class Manager implements Authority { public String action() { returns "I manages People"; } class SalesMan implements Authority { public String action() { returns "I Sell things Company makes "; } }