我在看一篇关于好的 API 设计的博客 link text
在标题为“重新发明套接字”的示例部分之一中,它展示了如何在使用它的客户端代码上强制执行某些规则和先决条件的设计。例如。客户端必须先调用 bind() 才能调用 connect(),并且必须先连接才能发送() 或接收() 数据。
我更熟悉 C/C++,所以我在完全理解类设计如何执行 API 规则时遇到了一些麻烦。例如,如何防止客户端代码使用如下内容调用此 API:
SocketConnected s = socket.bind(localaddress, 1000);
//client doesn't call the connect() method
//and just calls the send() method right away.
//this line should give compile-time error
//because only bind() was called but not connect()
s.send(/* some data goes here */);
编译器如何以及为什么会捕获该错误?如果我正确理解子类继承,SocketConnected 是一个 SocketBound,它是一个 Socket。但是,如果客户端代码能够声明一个 SocketConnected 对象,您如何才能强制执行必须在允许 send() 和 receive() 之前调用 bind() 和 connect() 的规则?
谢谢
最佳答案
您通过仅提供 bind()
作为创建者来强制执行规则,并且在 SocketConnected
上没有公共(public)构造函数。除了通过 API 之外,没有其他方法可以实例化 SocketConnected
。是的,你可以声明一个那个类的对象,但是你不能自己创建一个;因此,在调用正确的创建者之前,您不能调用任何实例方法。
已添加:回复您对 bind().connect()
的评论:这只是链接的示例,有点像 fluent interface ,但具有控制调用顺序的类型限制。想想会发生什么。第一个 bind()
调用创建一个实例,然后您可以在该实例上调用 connect()
。链接作者提供的最后一个代码示例是一个对比:这就是传统伯克利风格套接字库的样子,其中s
是一个套接字,bind()
和 connect()
都可以在其上以任何顺序调用,而不会引起编译器的提示。
添加:重新设计模式 - 我不认为它已被命名。它可能应该是。它支持 fail fast 设计标准的变体,早在编译器阶段就失败了。
关于java - Java 继承如何用于执行程序要求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3303555/