Does Java 8 provide an alternative to the visitor pattern?

后端 未结 3 1961
栀梦
栀梦 2021-02-07 14:22

This popular answer on Stack Overflow has this to say about the difference between functional programming and object-oriented programming:

Object-oriented

3条回答
  •  不要未来只要你来
    2021-02-07 14:29

    The additions made to the Java language do not render every old concept outdated. In fact, the Visitor pattern is very good at supporting adding of new operations.

    When comparing this pattern with the new Java 8 possibilities, the following becomes apparent:

    • Java 8 allows to easily define operations comprising a single function. This comes handy when processing flat homogeneous collections like with Iterable.forEach, Stream.forEach but also Stream.reduce
    • A visitor allows to define a multiple functions which are selected by element type and/or topology of a data structure which becomes interesting right where the single function feature stops working, when processing heterogeneous collections and non-flat structures, e.g. trees of items

    So the new Java 8 features can never act as a drop-in replacement for the Visitor pattern, however, searching for possible synergies is reasonable. This answer discusses possibilities to retrofit an existing API (FileVisitor) to enable the use of lambda expressions. The solution is a specialized concrete visitor implementation which delegates to corresponding functions which can be specified for each visit method. If each function is optional (i.e. there is a reasonable default for each visit method), it will come handy if the application is interested in a small subset of the possible actions only or if it wants to treat most of them uniformly.

    If some of these use cases are regarded “typical”, there might be an accept method taking one or more functions creating the appropriate delegating visitor behind the scene (when designing new APIs or improving API under your control). I wouldn’t drop the ordinary accept(XyzVisitor), however, as the option to use an existing implementation of a visitor should not be underestimated.

    There’s a similar choice of overloads in the Stream API, if we consider a Collector as a kind of visitor for a Stream. It consists of up to four functions, which is the maximum imaginable for visiting a flat, homogeneous sequence of items. Instead of having to implement that interface, you can initiate a reduction specifying a single function or a mutable reduction using three functions but there are common situations where specifying an existing implementation is more concise, like with collect(Collectors.toList()) or collect(Collectors.joining(",")), than specifying all necessary functions via lambda expressions/ method references.

    When adding such support to a particular application of the Visitor pattern, it will make the calling site more shiny while the implementation site of the particular accept methods always has been simple. So the only part which remains bulky is the visitor type itself; it may even become a bit more complicated when it is augmented with support for functional interface based operations. It is unlikely that there will be a language-based solution for either, simpler creation of such visitors or replacing this concept, in the near future.

提交回复
热议问题