= Solution
Use the \b[<adapter pattern>], keeping the existing component <software object> in both directions:
``
class PipeAsChannel(pipe: Pipe) extends Channel {
override def apply(n: Int): Int = {
pipe.consume(n)
pipe.result
}
}
class ChannelAsPipe(channel: Channel, initialResult: Int) extends Pipe {
private var last = initialResult
override def consume(n: Int): Unit = {
last = channel(n)
}
override def result: Int = last
}
``
The first adapter feeds the input before reading the pipe's output. The second invokes the channel exactly once per consume and caches its returned output; subsequent result queries do not advance it. \b[Its initial result must be supplied explicitly], because a general channel <object interface> exposes no initial-output query. Calling the channel on a dummy input during construction would mutate arbitrary state and would invent behavior the <object interface> does not promise.
These adapters preserve the sequential update/output behavior after each real input, assuming no interfering access to the wrapped component. They do not claim a perfect inverse for every aspect of the original <object interfaces>: pipe initialization is additional observable state, whereas a channel alone does not specify that observation.
Back to article page