0

I have a functional AdjacencyListGraph class that adheres to a defined interface GraphStructure. In order to layer limitations on this (eg. acyclic, non-null, unique vertex data etc.), I can see two possible routes, each making use of the GraphStructure interface:

  1. Create a single class ("ControlledGraph") that has a set of bitflags specifying various possible limitations. Handle all limitations in this class. Update the class if new limitation requirements become apparent.

  2. Use the decorator pattern (DI, essentially) to create a separate class implementation for each individual limitation that a client class may wish to use. The benefit here is that we are adhering to the Single Responsibility Principle.

I would lean toward the latter, but by Jove!, I hate the decorator Pattern. It is the epitome of clutter, IMO. Truthfully it all depends on how many decorators might be applied in the worst case -- in mine so far, the count is seven (the number of discrete limitations I've recognised at this stage). The other problem with decorator is that I'm going to have to do interface method wrapping in every... single... decorator class. Bah.

Which would you go for, if either? Or, if you can suggest some more elegant solution, that would be welcome.

EDIT: It occurs to me that using the proposed ControlledGraph class with the strategy pattern may help here... some sort of template method / functors setup, with individual bits applying separate controls in the various graph-canonical interface methods. Or am I losing the plot?

Engineer
  • 8,529
  • 7
  • 65
  • 105
  • @Nick Wiggill: I'd go with a decorator (which can be used both to add and, less known, to remove responsibilities) but why hate it? It's the opposite of clutter: without a decorator you'll end with clutter & the kitchen sink in your ControlledGraph. Note that modern IDEs can generate all the delegate calls to the wrapped subject in *one* shortcut. One of the major point of OO done correctly is to be able to adapt to everchanging requirements. If requirements are carved in stone, then depending on an implementation (ControlledGraph) that uses bitfields may be ok, but this is not OO. – SyntaxT3rr0r Mar 24 '10 at 22:48
  • I agree with you, which is why I mentioned the SRP. I can tell you that I already have a half-complete version of that particular implementation lying here, and it is *not* pretty. But see my answer below and you'll see a more elegant solution that encapsulates the functionality for each limitation, providing a much more extensible architecture, and without the clutter of decorator (it IS clutter -- I'm sorry but an undetermined level of constructor nesting is just plain silly). – Engineer Mar 24 '10 at 23:06

1 Answers1

0

Ah, I see it now. The strategy pattern in a ControlledGraph class is indeed the way to go.

Each limitation is a discrete strategy class. Each of these implements the entire GraphStructure interface, although most methods will be left empty (eg. an acyclic limitation is only interested in using addEdge() to prevent cycle insertions, others methods will be left empty).

Each time the ControlledGraph has one of its interface methods called, it will call the matching methods of each of the strategies/limitations it contains. It may hold only one of each type of strategy, obviously.

Engineer
  • 8,529
  • 7
  • 65
  • 105