Java 具有不断变化的接口的装饰器模式

Java 具有不断变化的接口的装饰器模式,java,database,oop,design-patterns,Java,Database,Oop,Design Patterns,我有一个用例,其中我有一个由外部供应商提供的数据库接口,假设它如下所示: interface Database{ public Value get(Key key); public void put(Key key, Value value) } 供应商提供此接口的多种实现,例如ActualDatabaseImpl、MockDatabaseImpl。我的消费者希望使用数据库接口,但在调用某些API之前,他们希望执行一些额外的工作,例如在进行调用之前调用客户端速率限制器。因此,

我有一个用例,其中我有一个由外部供应商提供的数据库接口,假设它如下所示:

interface Database{

   public Value get(Key key);

   public void put(Key key, Value value)

}
供应商提供此接口的多种实现,例如ActualDatabaseImpl、MockDatabaseImpl。我的消费者希望使用数据库接口,但在调用某些API之前,他们希望执行一些额外的工作,例如在进行调用之前调用客户端速率限制器。因此,与其让每个消费者都去做额外的检查RateLimitor限制的工作,我想创建一个装饰类,它将抽象出rate Limitor部分,消费者可以在不知道RateLimitor逻辑的情况下与DB交互。e、 g

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,例如delete/getDBInfo/deleteddb等,问题就开始出现了

每当发布具有更新方法的DB的新版本时,我的RateLimitedDatabase构建就会中断。一种选择是在修饰类中实现新方法,以调查构建失败的根本原因,但这对开发人员来说只是额外的痛苦。如果在不断变化/扩展的接口中使用装饰器模式,这似乎是一个常见的问题,那么还有其他方法来处理这种情况吗

注意:我也可以考虑构建一个基于反射的解决方案,但对于这个特定的问题来说,这似乎是一个过激/过度工程。

如果这是可行的(您需要修改所有的客户端代码),您可以提取
供应商.Database
接口的“镜像”,并将其称为
镜像.Database
;然后从
vendor.Database
界面将所需的方法复制到
mirror.Database
(具有完全相同的签名)

编辑客户端代码以使用
mirror.Database
界面,并让
RateLimitedDatabase
实现此
mirror.Database
界面。由于所有方法签名都是相同的,因此将客户机代码切换到镜像接口应该是无痛的
RateLimitedDatabase
将委托给
供应商。当然,数据库的实施


(我认为我描述的或多或少是桥接模式(使用接口“屏蔽”底层更改)。

面向方面编程解决了这个问题。 大多数框架都会为你的界面生成一个动态代理,所以它总是同步的