Я думаю, вы могли бы использовать контейнер IOC, например Spring, чтобы получить такое поведение.
Создайте любую задачу, которая должна выполняться только один раз, как одиночную, и пусть конструктор объекта задачи запустит задачу. Тогда любой объект, который приходит позже с зависимостью от этой задачи, получит ссылку на уже выполненную задачу и сможет получить результаты этой задачи или сможет сделать вывод, что эта задача уже была успешно выполнена.
В весеннем конфиге вы получите множество задач, связанных друг с другом, каждая из которых ссылается на другие задачи в своем конфиге конструктора.
Этот подход является наиболее гибким, и вы не ограничены «задачами» или чем-то слишком тяжелым в этом отношении.
Я предполагаю, что любая библиотека рабочих процессов также имеет схожие концепции. Но я не очень знаком с ними.
Я думаю, что для чего-то меньшего, люди должны просто свернуть свой собственный объектный граф и интерфейс, используя шаблон посетителя и, возможно, Словарь для хранения состояния.