java - 带有 final方法的 Java 类装饰器

标签 java decorator final

我有一个 (Java) 类 WindowItem,它有一个问题:其中一个方法不是线程安全的。我无法修复 WindowItem,因为它是外部框架的一部分。所以我想我为它实现了一个装饰器,它在相关方法上有一个“同步”关键字。

Decorator 扩展 WindowItem 并且还将包含 WindowItem。按照 Decorator 模式,我在 Decorator 中创建调用它包含的 WindowItem 的方法。

但是,WindowItem 有几个 final方法,我不能在装饰器中覆盖它们。这打破了装饰器的透明度。让我们明确一点:

public class WindowItem {
   private List<WindowItem> windows;

   public Properties getMethodWithProblem() {
      ...
   }

   public final int getwindowCount() {
      return windows.size();
  }
}

public class WindowItemDecorator extends WindowItem {
   private WindowItem item;

   public WindowItemDecorator(WindowItem item) {
      this.item = item;
   }

   # Here I solve the problem by adding the synchronized keyword:
   public synchronized Properties getgetMethodWithProblem() {
      return super.getMethodWithProblem();
   }

   # Here I should override getWindowCount() but I can't because it's final
}

在我自己的代码中,每当我必须在某处传递 WindowItem 时,我首先将其包装在装饰器中:new WindowItemDecorator(item) —— 线程安全问题就消失了。但是,如果我的代码在 WindowItemDecorator 上调用 getwindowCount(),它将始终为零:它在父类(super class)而不是“item”成员上执行 getWindowCount()。

所以我想说 WindowItem 的设计(事实上它有 public final 方法)使得不可能为这个类创建装饰器。

这是正确的,还是我遗漏了什么?

在这种情况下,我可能能够在装饰器中保留一份窗口列表的副本,并使其保持同步,然后 getWindowCount() 的结果将是正确的。但在那种情况下,我更愿意 fork 和修补框架......

最佳答案

不这样想问题怎么样?为什么不直接处理代码中的线程问题,而不假设 WindowItem 的线程安全。

// I personally prefer ReadWriteLocks, but this sounds like it will do...
synchronized (windowItem) {
    windowItem.getMethodWithProblem();
}

然后向包维护者提交 RFE,以更好地支持线程安全。

确实,如果该类不是设计为线程安全的,那么一些 synchronized 关键字不太可能真正解决问题。有人所说的“线程安全”总是相对的;-)

(顺便说一句,WindowItem 绝对不是线程安全的,因为它使用 List 而不是显式使用“线程就绪”变体 Correct way to synchronize ArrayList in java -也不能保证以线程安全的方式访问 List

关于java - 带有 final方法的 Java 类装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11774800/

相关文章:

python - 如何通过 flask.Blueprint.route 装饰器传递类的 self ?

java - Servlet 页面装饰 : Do people use Tiles, Sitemesh,还是别的?

java - JVM 如何处理类中的 final 变量?

java - for循环条件部分的final关键字

java - java中的"Final"和复制二维数组

java - 我应该把上传的图片放在 java 应用程序的服务器上的什么地方?

java - 如何通过名称获取 OSGi 包的安装目录(绝对路径)?

java - 记录已删除对象的 BlockingQueue 装饰器

java - 计算字符串中的空格数

java - 从java代码运行时如何将参数传递给ant脚本?