【问题标题】:How to implement an Observer-pattern with two packages如何使用两个包实现观察者模式
【发布时间】:2019-11-13 11:48:52
【问题描述】:

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

这是一个虚构的例子: 包“Gaming”包含“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);
}

感谢您提供的所有答案。

【问题讨论】:

  • 你的界面名称告诉你:玩家..
  • 如果您将 playersgaming 制作成单独的模块,您肯定会注意到。现在,如果你添加第三个模块也想通知玩家,你宁愿依赖 player 而不是 gaming

标签: java package naming


【解决方案1】:
    core
    ^  ^
    |  |
    | player
    |    ^
    |    |
    gaming
  • 与播放器完全保持Player-focused 项目
  • 不要直言不讳。 IEverything 模式可以追溯到Hungarian notation,现在根本不需要。如果您的接口是代码将引用的主要事物,请为其命名。
  • 您可能可以像我在下面所做的那样对Observable 接口进行通用化,并将其放入通用的“核心”包中
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) {}

【讨论】:

【解决方案2】:

就像 David Pérez 在他的评论中所说:你的接口名称已经告诉你了。 将观察玩家所需的所有内容分组在一个包中是有意义的,这样另一个包只需要导入玩家包。

【讨论】:

    猜你喜欢
    • 2011-12-21
    • 1970-01-01
    • 1970-01-01
    • 2017-01-23
    • 1970-01-01
    • 1970-01-01
    • 2013-10-28
    • 2013-12-03
    • 1970-01-01
    相关资源
    最近更新 更多