如何用两个包实现观察者模式

How to implement an Observer-pattern with two packages

我和一个朋友讨论如何用两个包实现观察者模式。

这是一个虚构的例子: 包 "Gaming" 包含 class "Battlefield"。 包 "Players" 包含 "IPlayer"(以及该接口的各种实现)。

现在我们要战场观察玩家。为此,我们创建了一个接口 "IPlayerObserver" 和 "IOberservablePlayer"。 IPlayer继承IOberservablePlayer.

我们应该把"IPlayerObserver"放在哪个包里?

// Package: Players
public interface IPlayer extends IOberservablePlayer {}

// Package: Gaming
public class Battlefield implements IPlayerObserver {}

// Which package?
public interface IPlayerObserver {
     void notify(IPlayer player);
}

public interface IOberservablePlayer {
     void addObserver(IPlayerObserver observer);
}

感谢所有有益的回答。

正如 David Pérez 在他的评论中所说:您的接口名称已经告诉您了。 将观察玩家所需的一切都集中在一个包中是有意义的,这样另一个包只需要导入玩家包。

    core
    ^  ^
    |  |
    | player
    |    ^
    |    |
    gaming
  • 与玩家保持完全 Player 重点项目
  • 不要直言不讳。 IEverything 模式可以追溯到 Hungarian notation,现在根本不需要。如果您的界面是代码将引用的主要内容,请为其命名。
  • 您可以像我在下面所做的那样通用化 Observable 接口,并将其放入通用的 "core" 包中
package com.yourname.player;
public interface Player extends Oberservable<PlayerObserver>

package com.yourname.gaming;
public class Battlefield implements PlayerObserver 

package com.yourname.player;
public interface PlayerObserver {
     void notify(Player player);
}

package com.yourname.core;
public interface Oberservable<T> {
     void addObserver(T observer);
}

此外,不直接在其他重要 类 上实现此类侦听器会稍微干净一些,因为它向所有人公开了 Battlefield.notify(Player) 等方法,而只有 Player 打算调用它。

尝试在 Battlefield 中执行此操作:

player.addObserver(this::playerNotification)
...
private void playerNotification(Player p) {}