1

Is there an elegant solution or pattern so that one invoke of writeStartObject() can be applied to both the Writer and the OutputStream?

        try (
        JsonGenerator output = jfactory.createGenerator(outputWriter); // writer
        JsonGenerator cachingOutput = jfactory.createGenerator(cachingService.getCachingOutputStream(id));//outputstream
    ) {
        output.writeStartObject();
        cachingOutput.writeStartObject();
        ...
Viktor Baert
  • 686
  • 8
  • 22
  • 1
    I guess you can use the [facade design pattern](https://stackoverflow.com/questions/5242429/what-is-the-facade-design-pattern). But I think that is more overhead and does not bring much more readability. – flaxel Sep 24 '20 at 17:22

1 Answers1

1

You may want to consider whether these two really should be bound together as there are cohesion and coupling guidelines to consider. For example, if you need to use the writer or the outputStream for other uses and to an extensive degree then you should keep them separate unless this extensive use is reflected across both of them equally. It may be better to hide both of these behind two independent Data Access Objects where their use can be compartmentalized, exposing their operations in a descriptive manner based on the purpose for accessing them - a little more suited to your business.

Whether it's limited use or extensive use, for equal use across the pair I might apply a façade as such:

class SimultaneousFeed {
    private JFactory jFactory;
    private JsonGenerator out;
    private JsonGenerator writer;
    SimultaneousFeed(JFactory jFactory, OutputStream outputStream, Writer outputWriter) {
        this.jFactory = jFactory;
        this.out = jfactory.createGenerator(outputStream);
        this.writer = jfactory.createGenerator(outputWriter);
    }
    void writeStartObject() {
        out.writeStartObject();
        writer.writeStartObject();
    }
    ...
    // other operations common to the pair of these outputs
}

...

SimultaneousFeed feed = new SimultaneousFeed(jFactory, cachingService.getCachingOutputStream(id),
        outputWriter);
feed.writeStartObject();

Note that I'm passing the OutputStream to the new SimultaneousFeed instance rather than passing the id. Passing the id raises the data coupling in the new instance - the id is a piece of data the SimultaneousFeed should know nothing about. This allows the SimultaneousFeed to concern itself with only output data, improving reusability and maintainability.

An alternative pattern to consider would be the Decorator pattern, provided you're able to subclass the class of the jfactory instance and the JsonGenerator class. This would allow you to create a custom JsonGenerator that simultaneously writes to the two outputs in an overridden implementation of the writeStartObject() method. In that case, you could provide a method in the jfactory class:

public JsonGenerator createSimultaneousGenerator(OutputStream outputStream, Writer outputWriter) {
    return new SimulJsonGenerator(outputStream, outputWriter);
}
dan
  • 741
  • 9
  • 14