Если вы очень строго придерживаетесь небольшого набора интерфейсов, вы можете использовать объекты-оболочки, которые делают следующее:
- Реализация интерфейса
- Журнал / запись входов
- Делегировать вызов базовому объекту
- Записать / записать результат
- Вернуть результат вызывающей стороне
Вы также можете изменить фабричные методы так, чтобы они возвращали обернутые объекты, а не нижележащие объекты, чтобы использование этих оболочек было достаточно прозрачным.
Обратите внимание, что вам нужно быть очень осторожным с изменчивостью параметров: в идеале все параметры должны быть неизменяемыми, но если нет, вам нужно будет делать глубокие копии (возможно, через сериализацию).
Теоретически вы можете также использовать зарегистрированные входы для включения воспроизведения и / или тестирования .... но я бы с осторожностью ожидал от этого слишком многого, так как воспроизведение потребовало бы, чтобы вы зафиксировали все релевантные состояние (включая внешнее состояние, такое как транзакция с БД, доступ к файловой системе и т. д.) В общем, этого трудно достичь, хотя вы могли бы заставить его работать в вашем конкретном случае.