Java 将finalize()与Decorator模式一起使用
我正试图解决一个设计问题。简而言之,可以使用Java 将finalize()与Decorator模式一起使用,java,decorator,backwards-compatibility,Java,Decorator,Backwards Compatibility,我正试图解决一个设计问题。简而言之,可以使用finalize()来释放仅与该对象相关且仅在该对象存在时可用的私有静态资源吗?详情如下 首先是限制条件: 我正在使用decorator模式封装一个类型(X) 我没有写信 X是最终版,因此不可能对其进行子类化 我在包装器中有一个方法,比如说x(),它在任何时候都会 返回基础X实例 之所以使用x(),是因为包装器类型需要 可与预期为X 参数 包装器有一个构造函数,它将X实例作为 参数然后将其封装的X对象设置为 例如 问题是: 我想在包装器中添加一些功能/
finalize()
来释放仅与该对象相关且仅在该对象存在时可用的私有静态资源吗?详情如下
首先是限制条件:
我正在使用decorator模式封装一个类型(X
)
我没有写信
X
是最终版
,因此不可能对其进行子类化
我在包装器中有一个方法,比如说x()
,它在任何时候都会
返回基础X实例
之所以使用x()
,是因为包装器类型需要
可与预期为X
参数
包装器有一个构造函数,它将X
实例作为
参数然后将其封装的X
对象设置为
例如
问题是:
我想在包装器中添加一些功能/数据,但要保留它。我的意思是,当包装被“取消包装”到X
时,它可以在代码中的其他某个点被“重新包装”到包装,并且,即使额外的数据没有在底层X
中携带,也会被恢复
到目前为止,我的想法是:
如果我在包装器类中创建一个静态映射,其中键是唯一的X
id,并且该值是某些结构中的额外数据,那么我可以在rewrap(X)
方法中检索它
我不会使用包装器或X
对象作为映射中的键,因为这将阻止它可能被GC'd(除非从映射中显式删除),因此我们将使用唯一的hashcode
虽然这在原则上看起来还可以,但问题是何时从静态映射中删除这些额外数据。在这种情况下,我们可以允许finalize()的实现:
这是我的理由。。。我们都知道,通常依赖finalize()来释放资源是个坏主意,但这里讨论的资源直接与对象相关。没有对外部资源的引用,因此我们需要这些内部资源,直到包装器对象本身被GC’d,在这一点上,我们只是删除资源映射
最坏的情况是不必担心删除这些冗余的静态映射,因为这会导致内存泄漏
我想不出任何其他方法来实现此功能并保持与现有API的向后兼容性:
public void foo(Wrapper wrapper){
bar(wrapper.x());
}
public void bar(X instance){...}
这就是问题所在,有其他的方法或观点吗
非常感谢
编辑:
在进一步研究之后,我想我会更新这个问题,因为如果每次需要访问x实例时都显式调用Wrapper.x,那么类似的情况可能是的主要候选情况,那么您不能向Wrapper添加一个cleanup方法,并在除去Wrapper对象之前显式调用它吗
也可以从finalize调用cleanup方法,以确保在未显式调用它时将其清除。这将为您提供两个世界中最好的一个,因为如果包装器使用不当,您将有更大的机会减少内存泄漏
void someRandomMethod() {
Wrapper someWrapperINeed = new Wrapper(new X(blah, blah blah));
foo(someWrapperINeed);
someWrapperINeed.clean();
// Instead of foo(new Wrapper(new X(blah, blah, blah));
}
// Or foo can call clean if the wrapper will never be needed after its invocation
void foo(Wrapper w) {
bar(w.x());
w.clean();
}
编辑:添加代码示例 我刚刚编辑了这个问题,因为我不够清晰,很抱歉。额外的数据直接与X实例关联,因此需要保留这些数据,以防以后重新包装未包装的X实例。因此,我无法处理x()中的额外数据。wrapperKey是否与x实例相关?这样,您就可以查找额外的数据,并通过了解X来重新创建包装器对象?在这种情况下,为什么不直接使用X对象作为关键点?你怎么能从包装器的finalize方法中删除额外的数据呢?那么在重新创建包装器之前,您可能会丢失数据。这是一个很好的观点。密钥需要直接与X相关,因为包装器是一次性的,可以随时重新创建。在本例中,删除这些额外数据需要在X的finalize中完成,因为包装器不知道这是否是X最后一次包装。六羟甲基三聚氰胺六甲醚。。。有没有想过用另一种方法来实现同样的目标?是否只有“遗留”代码可以控制X何时被处理?您是否可以监听某种事件,以便能够在适当的时间处理包装器中的数据?需要X实例的类是否可以子类化?包装器是位于现有API之上的层/插件的一部分。令人沮丧的是,没有任何回调可以连接到。。。看起来我能做的最好的事情就是将额外的数据存储在包装器中,而不是保存它。或者让客户负责处理额外的数据。。但这可能有点不友好?
void someRandomMethod() {
Wrapper someWrapperINeed = new Wrapper(new X(blah, blah blah));
foo(someWrapperINeed);
someWrapperINeed.clean();
// Instead of foo(new Wrapper(new X(blah, blah, blah));
}
// Or foo can call clean if the wrapper will never be needed after its invocation
void foo(Wrapper w) {
bar(w.x());
w.clean();
}