您是否应该始终使用Java编写接口代码

您是否应该始终使用Java编写接口代码,java,interface,oop,Java,Interface,Oop,我理解为接口编码的原则——将实现与接口解耦,并允许接口的实现进行交换 我应该为我编写的每个类的接口编写代码,还是这样做太过分了?我不想让一个项目中的源文件数量翻一番,除非它真的值得 我可以使用哪些因素来决定是否按接口编码?不,每个类都不应该有接口。这太过分了 当您需要从如何完成抽象出所做的事情,并且您确信实现可以更改时,您可以使用接口 查看java.util集合API以获得一个好的示例。列表接口对于列表的一般概念来说是一个很好的抽象,但是您可以看到实现它的方法有很多:ArrayList、Link

我理解为接口编码的原则——将实现与接口解耦,并允许接口的实现进行交换

我应该为我编写的每个类的接口编写代码,还是这样做太过分了?我不想让一个项目中的源文件数量翻一番,除非它真的值得


我可以使用哪些因素来决定是否按接口编码?

不,每个类都不应该有接口。这太过分了

当您需要从如何完成抽象出所做的事情,并且您确信实现可以更改时,您可以使用接口

查看java.util集合API以获得一个好的示例。列表接口对于列表的一般概念来说是一个很好的抽象,但是您可以看到实现它的方法有很多:ArrayList、LinkedList等等

更新:那么,如果您设计了一个具体的类,在拥有客户机之后决定是否需要一个接口,然后通过添加一个接口来破坏客户机,又会怎么样呢?是的,事情就是这样。你怎么知道你不知道的?没有任何软件或方法可以解决这一问题

对您来说,好消息是从一个具体的类中提取接口对于您和您的客户机来说都是一件容易的重构工作。IDE通常会处理这种事情。你和你的客户应该利用他们

我要说的是,像服务和持久性这样的层应该总是有接口的。任何可以代理的东西都应该有一个接口。如果您正在执行SpringAOP,那么您想要用方面来装饰的任何东西都应该有一个接口

模型或值对象,如Person、Address或Phone,不应具有接口。不可变值对象不应具有接口


其余的则属于灰色地带。使用你最好的判断。

我使用它时,至少有一个是正确的:

1) 我希望将不相关的模块/类彼此解耦,并希望通过java包依赖项反映出来

2) 当解耦在构建依赖性方面很重要时

3) 当实现可能通过配置或在运行时动态更改时(通常由于某些设计模式)

4) 当我希望一个类是可测试的时,我将它的“链接点”设置为外部资源接口,以便使用模拟实现


5) 不太常见:当我想有一个选项来限制对某个类的访问时。在这种情况下,我的方法返回的是一个接口而不是实际的类,因此调用方知道我不希望他对返回的值执行其他操作。

长话短说,不。您是应用程序的创建者,因此您对可能发生的变化有一个合理的想法。在我看来,一些设计模式书对此有点疯狂,因为它们似乎总是将设计推向接口,而不是实现。有时候,这只是矫枉过正。对于我最新的应用程序(小尺寸),我有一个数据库接口,因为我认为有可能稍后将其移植到web并切换到MySQL。当然,在现实中,在现有类的基础上创建一个数据库接口是很容易的,只需在稍后添加“implements myDbInterface”,并进行一些小的更改。这是可行的,因为我是唯一的开发者。对于一个更大的团队,或者不同类型的产品,这可能是一个不同的答案。只要使用你最好的判断(当然,在阅读了所有好的SO答案之后)。

一般来说,我同意其他答案:当你知道或预期变化和/或不同的实现时,使用接口,或者追求可测试性

但是提前知道未来会发生什么变化并不总是容易的,特别是如果你没有那么丰富的经验的话。我认为解决这个问题的办法是重构:只要不需要,就保持简单(=没有接口)。当需要时,只需进行“引入/提取接口”重构(几乎所有体面的IDE都支持)

当您这样做时,只提取调用方实际需要的那些方法。不要害怕提取多个单独的接口(如果不是所有提取的方法都是一致的)

<> P>一个重构的驱动程序可能是测试:如果不能很容易地用类来测试某件事,只考虑引入一个/一些接口。这还允许您使用模拟,这在许多情况下可以大大简化测试

编辑:根据塔尔斯基的评论,我意识到对前面的陈述还有一个更重要的场景/调整:
如果您提供一个外部API(用于其他[子]项目,或真正将其“发布到野外”),那么在API中使用接口(除了简单的值类)几乎总是一个好主意。

如果您愿意,它将允许您在不干扰客户端代码的情况下更改impl。只有当您还必须更改接口时,才会出现问题。不破坏兼容性将非常棘手(如果不是不可能的话)

我喜欢认为,当可插拔性和不同行为的可能性很重要时,人们会使用接口。服务是最合适的。人们可能想要一个默认的实现,但伪造(模仿)等是另一个。这显然意味着应该有一个intf,因为它总是至少有两个表单


另一方面,值类型应该是final类。它们永远不应该延长。值类型包括郊区、MimeType等。如果这些成分有变化,则使用成分。作为一个目标,我尝试在我的价值观类型中加入很少的行为(如果有的话)。验证它包装的简单类型等可能是它所做的最复杂的事情。例如,采用r/g/b的颜色类应验证每个组件是否介于0和255之间,即此值。

是当您希望行为发生更改时,请使用界面
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 ";
}
}