【问题标题】:Avoid exposing implementation details when implementing an observer pattern in Java?在 Java 中实现观察者模式时避免暴露实现细节?
【发布时间】:2023-03-08 23:31:01
【问题描述】:
我从 C# 来到 Java,其中事件是一等公民,事件处理程序可以是私有方法。我现在正在开发一个 Java 项目,当然我需要使用观察者模式来实现事件。
由于 Observer 需要将其侦听器/处理程序回调方法暴露给 Observable 类,这似乎是将 Observer 细节的实现暴露给其他不关心的类。我可以将这些方法的访问权限设置为包级别,这将使这些实现细节对我的包的消费者隐藏,但它对我来说仍然有一种不好的“气味”。
这只是我需要咬紧牙关,还是有更好的方法?
【问题讨论】:
标签:
java
design-patterns
observer-pattern
【解决方案1】:
使用观察者模式,您正在观察的类不需要公开它们的实现。通常,通知其他类的类会有自己的关联接口供其他类实现。
public interface Observer
{
public void handleSomeEvent(Object someObjectOfImportance);
}
public class Observable
{
public void register(Observer observer);
}
任何类都可以实现Observer 接口并注册自己而不暴露任何实现细节。它确实公开了它实现了一个接口,但没有指定 如何 它实现它。或者,您可以提供匿名实现。
public class SomeObserverImplementation implements Observer
{
public void handleSomeEvent(Object someObjectOfImportance)
{
// I can do whatever I want here
}
}
更新
如果您担心您的类现在公开一个新接口,有一些方法可以解决它。一种是创建匿名实现。另一个是您可以拥有一个实现 Observable 接口的私有内部类。
public class IDontWantOthersToKnowIObserve
{
private class HiddenObserver implements Observer
{
public void handleSomeEvent(Object someObjectOfImportance)
{
...
}
}
... in some method ...
theObservable.register(myHiddenObserver);
}
使用匿名实现:
theObservable.register(new Observer()
{
public void handleSomeEvent(Object someObjectOfImportance)
{
// ...
}
});
【解决方案2】:
在 Java 中,这通常不被认为是真正暴露实现细节,但是,如果你真的想对其他类隐藏你的类的功能,那么你需要让你的类实现不同的接口,每个接口只暴露一个子集整体类功能。如果您随后确保其他类仅通过特定接口(可能通过工厂)访问您的类,那么您实际上隐藏了您的实现。
例如:
public interface Observer<T>
{
public void notify(T event);
}
public interface PublicFace
{
public void doSomething();
}
public class SomeClass implements Observer<Event>, PublicFace
{
public void notify(Event event)
{
// ...
}
public void doSomething()
{
// ...
}
}
public class FaceFactory
{
public static PublicFace getPublicFaceInstance()
{
return new SomeClass();
}
}