假设以下场景:
我们有一个来自某个库的 Java 类,它消耗字节流,比如某个XmlParser1
公开方法的XML 解析器xmlParser1.parse(inputStream)
;该方法通常会在一次调用中吃掉所有字节,最终阻塞。我们还有另一个类,来自其他一些库,它做类似的事情,但实现不同:XmlParser2
with xmlParser2.parse(inputStream)
。现在,我们想用两个解析器解析一个流。
我的第一个答案是:我们搞砸了。由于我们无法控制每个类如何使用流,我们所能做的就是缓冲内存中的所有字节或临时文件(或打开/重新打开它,如果可能的话)。这些消费者的 API 本质上是不合作的。
现在,假设我们可以控制XmlParser1
(实现和签名)并且我们希望以更灵活和协作的方式对其进行编码,以便调用者可以以某种合理和有效的方式实现上述行为......你有什么建议?
我正在考虑的一些替代方案:
1) make XmlParser1
implement FilterInputStream
,这样当某个类 ( XmlParser1
) 尝试从中读取一些字节时,它会在内部解析它必须的内容(迭代地,也许有一些合理的缓冲)并返回原始字节。(这并不完全符合这个FilterInputStream
概念,我会说)。通过这种方式,客户端代码可以简单地链接解析器:
public class XmlParser1 extends FilterInputStream {
public XmlParser1(InputStream rawInputStream) { ... }
public int read(byte[] b, int off, int l) throws IOException {
// this would invoke the underlying stream read, parse internall the read bytes,
// and leave them in the buffer
}
}
XmlParser1 parser1 = new XmlParser1(inputstream);
XmlParser2 parser2 = new XmlParser2(parse);
parser2.parse(); // parser2 consumes all the input stream, which causes parser1 to read an parse it too
2)与其将 atXmlParser1
视为字节的消费者,不如将其视为一个接收器:我们不会让它吃掉自己的字节,我们会用勺子喂它。所以,不是xmlParser1.parse(inputStream)
我们可以有
xmlParser1.write(byte[])
... 也就是说,不是传递它 anInputStream
我们将使它成为一个OutputStream
. 这将允许客户端创建一个 TeeInputStream 将字节透明地传递给XmlParser2
类,同时调用XmlParser1.write()
请注意,在任何情况下我们都不需要单独的线程。
我不确定哪一个(如果有的话)在概念上更可取,是否有更好的选择。在我看来,这是一个应该已经讨论过的设计问题,但我没有找到太多 - 不一定仅限于 Java。欢迎提出意见和参考。