在Java中实现观察者模式时,避免暴露实现细节?

7

我从C#转到Java,发现在C#中事件是一等公民,事件处理程序可以是私有方法。而在Java项目中,我需要使用观察者模式来实现事件通知。

由于观察者需要将其回调方法暴露给被观察对象类(Observable),这似乎暴露了观察者的细节实现给其他无关的类。虽然可以将这些方法的访问级别设置为包级别,使得消费者仅能在同一包内使用,但我仍感觉不太舒服。

这只是我需要咬紧牙关忍受的问题,还是有更好的解决方案?

2个回答

9
使用观察者模式时,观察的类不需要暴露它们的实现。通常,用于通知其他类的类会有其自己相关的接口供其他类实现。
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)
                {
                                // ...
                }
            });

1
在Java中,通常不会认为这是真正暴露实现细节,但是如果您确实想要隐藏类的功能,则需要使您的类实现不同的接口,每个接口仅公开整体类功能的子集。 然后,如果您确保其他类仅通过特定接口(可能通过工厂)访问您的类,则可以有效地隐藏您的实现。

E.g:

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();
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接