У меня есть случай использования, когда у меня есть интерфейс базы данных, предоставленный внешним поставщиком, скажем, он выглядит следующим образом:
interface Database{
public Value get(Key key);
public void put(Key key, Value value)
}
Поставщик предоставляет несколько реализаций этого интерфейса, например ActualDatabaseImpl, MockDatabaseImpl.Мои потребители хотят использовать интерфейс DataBase, но перед вызовом некоторых API они хотят выполнить некоторую дополнительную работу, например, ограничить скорость на стороне клиента перед выполнением вызова.Поэтому вместо того, чтобы каждый потребитель мог выполнять дополнительную работу по проверке лимита rateLimiter, я подумал о создании декорированного класса, который будет абстрагировать часть ограничения скорости, и потребители смогут взаимодействовать с БД, не зная логику RateLimiter.например,
class RateLimitedDatabase implements Database{
private Database db;
public RateLimitedDatabase(Database db) {this.db = db;}
public Value get(Key key) {
Ratelimiter.waitOrNoop();
return db.get(key);
}
public void put(Key key, Value value) {
Ratelimiter.waitOrNoop();
return db.put(key, value);
}
}
Это работает нормально, если интерфейс базы данных не вводит новые методы. Но как только они начинают добавлять API, которые меня не особо волнуют, например, проблемы удаления / getDBInfo / deleteDB и т. д.начало возникать.
Всякий раз, когда выпускается новая версия БД с более новыми методами, моя сборка для RateLimitedDatabase ломается. Один из вариантов - реализовать новые методы в украшенном классе при исследовании первопричины сбоя сборки, но это простодополнительная боль для разработчиков.Есть ли другой способ справиться с такими случаями, так как это кажется распространенной проблемой при использовании шаблона Decorator с постоянно меняющимся / расширяющимся интерфейсом?
ПРИМЕЧАНИЕ. Я также могу подумать о создании решения на основе отражения, но этопохоже, это излишнее / чрезмерное решение этой конкретной проблемы.