使用Guava或其他lib避免访问者模式?

时间:2016-05-05 21:41:05

标签: java guava visitor-pattern

在某些情况下,访问者模式会产生不必要的复杂性和样板(许多接受方法),并且在我看来完全泛化是不可能的(accept()方法也返回值)。所以我认为在我的案例的另一个解决方案。

我当然不想创建很多if-else instanceof块,我想找到一种智能方法来匹配特定类型(例如列表中的方法)

例如 guava 在其EventBus中具有类似的功能,可以使用@Subscribe注释方法匹配特定类型的事件,所以我正在寻找一个类似的lib来实现这一点一般来说。

<小时/> 这是一个例子,我想要类似的东西:

神奇的界面:

/**  @param <R> - return type  * @param <I> - element super type */
public interface MagicDoubleDispatch<R, I>{
    R dispatch(I element);
}

我的访客&#34;实现(应该自动调用适当的方法)

public class EventFormatter extends MagicDoubleDispatchImpl<String, Event> {
    private String format(AddedEmployeeEvent event) {
        return String.format("Added new employee: %s with id %s", event.name, event.employeeId);
    }
    private String format(DeletedEmployeeEvent event) {
        return String.format("Deleted employee:(%s) %s (this can't be undone!)", event.employeeId, event.name);
    }
    private String format(AddedTimeCardEvent event) {
        return String.format("Timecard of %s has been added to %s", event.date, event.employeeName);
    }
}

我希望将其作为库(例如):

public abstract class MagicDoubleDispatchImpl<R, I> implements MagicDoubleDispatch<R, I> {
    //I want this ... probably using reflection as EventBus, I don't care..
}

客户代码:

private EventFormatter eventFormatter = new EventFormatter();

public List<String> toStringList(List<Event> events) {
    return events.stream()
        .map(it -> eventFormatter.dispatch(it))
        .collect(Collectors.toList());
}

2 个答案:

答案 0 :(得分:1)

不确定你的意思&#34; accept()方法的返回值也是&#34;但无论如何,借助代码生成器的帮助,访问者模式可以非常轻量级:查看https://github.com/derive4j/derive4j - 它提供了一种模式匹配语法,可以使您的代码具有可读性。

此外,没有其他技术/库可以提供与访客模式一样多的类型安全性。

答案 1 :(得分:0)

您可以创建一个Map,类将Event扩展为键,将一个函数转换为string。

Map<Class<T extends Event>,Function<T,String>>

如果你想要一些花哨的东西,你可以使用注释并根据这些注释创建一个注册表(容易用spring做)但基本上最终的结果是相同的。

EventFormatter根据它的类型在地图中查找给定事件的格式化程序并应用相应的函数。 如果事件类和格式化程序之间有1对1的映射,则应该没问题。

如果你需要回退到父类,如果没有给定类型的格式化程序,那就更烦人但是可行。