I'm trying to figure out how to apply composition over inheritance to a system I'm building, and tripping up when I try to apply it to my page objects.
The relevant objects are:
The system is pretty straight-forward. The
PageFactory is used to build and retrieve
Page objects. Pages use repositories to retrieve data objects for use when rendering the page and setting the page's title.
Before trying to apply composition over inheritance, each different page would be a subclass of the base
Page object, and would override
I've refactored the system such that there are no longer subpage objects, but instead
PageFactory creates an instance of
Page for each type of page and sets the appropriate properties through setter functions (think view template path, route string, etc).
The problem is that each page needs to be able to retrieve data specific to that page using entity ids retrieved via route tags (like /entity/284), and also set the page's title based on the retrieved data, too.
This behavior is not easily refactored to config data. This is actual code that differs between pages.
The first approach I tried was to create an interface called
iDataProvider and then in the
PageFactory I would give each
Page instance the appropriate concrete
[entity]DataProvider object which would then have its own
Page objects would retrieve all query data and pass them to the
iDataProvider object when requesting data and title.
It works, but it feels icky, and I'm not 100% why. I think my feeling of unease may have something to do with passing all query data to the data provider and then asking it to know how to extract the important bits.
The second approach I tried was to have a single
RouteDataProvider object which accepts a
Route object, uses the
Route object to get all query data, and then based on what query tags are in that route retrieves the appropriate entities and passes them back to the page. This really doesn't feel much better.
I feel like I'm designing myself into a corner. Where did I make the wrong turn, and what would be a better way to design this part of my system?