Search code examples
oopdesign-patternsarchitecturesoftware-designfactory-pattern

Are there any common strategies for choosing an object type to create based on the type of another object


Imagine I have an object that could be any of a number of different types that all derive from a single base type. I want to create a second object which is related to the first object in the sense that its type is dependant on the type of the first object. The type of the second object will however always derive from a second base class.

My go to solution would be to have the first object create the second object through a virtual method.

In this particular situation however, we do not want the two classes to be coupled at all. Neither object should have any existence of the other object.

This means there must be some kind of third-party mediator object creating the second object based on the first objects type.

My next chosen solution would therefore be to have this mediator be a factory which looked specifically at the type of the first object and instantiated the second object based upon it.

To me this works, but seems not an ideal solution. If a factory is creating the first object then whenever a new derived type is added two factories must be updated and a new connection made.

Are there any common design patterns that could help with this and make the code cleaner?

Edit: As mentioned by @MustehssunIqbal. This problem is a classic case of parallel hierarchies. The problem with solving this by creating a bridge or similar method is that the two classes need to remain decoupled.

A concrete example is provided:

Lets say I have a base processor class that is inherited by many processor sub-classes. This is fine for the current application. A new application however also wants to use these classes and this is a GUI application. This application wants to create a GUI element for each processor and each individual type of processor must also have a specific GUI type.

Now to stop the GUI's being required in the first application, the processor and GUI classes must be decoupled.


Solution

  • Thanks for the details. It seems like the case of parallel hierarchies. You have many UI elements like button, list - but when it comes to draw these, you have three buttons for three processors, three TextAreas for three processors, and so on.

    Parallel hierarchies in UI layer for each type of processor

    As mentioned in the comment, I would suggest implementing the Bridge pattern, where the things specific to different processors can be abstracted. ProcessorRenderer (diagram below) is the abstracted thing that can be used by the UI layer.

    Bridge between UI elements (Glyph) and ProcessorRenderer

    Another similar approach would be to use an Application Facade layer. As you mentioned in your edit, you need to separate the Processor hierarchy from the UI layer. I also agree with this. I wouldn't want the UI layer to know anything about the Processors (or anything from the Domain layer). UI layer should be dumb and it should just draw things like buttons, lists, radio buttons, etc. So I would suggest to introduce an Application Facade layer, which would know about the Processor hierarchy from the Domain layer, and would know different types of UI elements from the UI layer, but should not know "how to draw the UI elements" -> that part should only be known by the dumb UI layer. UI layer would be testable irrespective of the Domain, and Domain doesn't know anything about the UI. What the Application Facade layer contains is the conversion of Domain layer objects into data structures that can be used by the UI layer. There's a lot more about Application Facades you can read about here: https://www.martinfowler.com/apsupp/appfacades.pdf

    Bridge pattern: https://en.wikipedia.org/wiki/Bridge_pattern

    I see Application Facade as a special case of Bridge pattern here, except that the Application Facade (ProcessorRenderer) has a dependency on the UI layer, while in the Bridge pattern the dependency is the other way around. But that's just my opinion.

    I dismissed the idea of using the Visitor pattern here since you mentioned in the edit that you want to completely decouple the UI layer from the Processor hierarchy. Also because if all that is done in the hierarchy is rendering, then there is just one impl of Visitor, i.e. RenderingVisitor. That would be completely okay, but I think it would be an overkill for making it a visitor. However, if you have many such different operations on the individual types of processors, where each operation is different for each type of processor, then I would recommend using the Visitor pattern instead. :)

    Visitor pattern:https://en.wikipedia.org/wiki/Visitor_pattern#:~:text=In%20object%2Doriented%20programming%20and,structures%20without%20modifying%20the%20structures.