Polymorphism vs. division of responsibilities: how

2019-04-12 15:39发布

问题:

In designing systems with hierarchical relationships, I often run into a problem that begs for polymorphic behavior, but there is more than one type of work that benefits from this polymorphic implementation.

For instance, consider a compiler that uses an abstract syntax tree to organize the parsed source for compilation. It's convenient to organize the logic polymorphically, as you might have more than one type of ValueProvider, each of which is responsible for the emission of different code to load the value onto the operation stack. The problem is that you might also want to perform static analysis on the AST, in which case you want to do completely different work with the tree, but nevertheless may have behavior that depends on the type of the node being analyzed. In other words, you want polymorphic behavior, but you don't want to co-mingle the analysis code with the compilation code.

The way I currently approach this is to store the data with an object model whose responsibility is to merely provide the tree. Each consumer of the tree (e.g. the compiler or the static analyzer) then uses run-time type information to perform conditional branching of its logic. This inevitably leads to a lot of 'if/else if' or 'switch' coding, based on the type of the nodes. It's just this type of ugly branching that polymorphism is designed to address, but the parallel, disjoint responsibilities seem to require it.

Is there a better way to structure this?

回答1:

You appear to be looking for the Visitor pattern:

the visitor design pattern is a way of separating an algorithm from an object structure on which it operates. A practical result of this separation is the ability to add new operations to existing object structures without modifying those structures.

(emphasis mine)