4

我对Java相当陌生。我来自 PHP,我曾经使用魔术 __get 和 __set 方法在 php 中创建注册表类。这样系统的其他部分就可以轻松做到:

registry.foo = new Foo();

我应该提到我正在尝试创建游戏引擎。这是我在 Java atm 中的注册表:

class Registry {

    private static Map<String, Object> box = new HashMap<String, Object>();

    public static Object get(String key) {

        if (Registry.box.get(key) != null) {
            return Registry.box.get(key);
        }else {
            return null;
        }
    }

    public static void set(String key, Object o) {
        Registry.box.put(key, o);
    }

}

然后为了系统的其他部分访问注册表,我目前需要这整件事:

((Object) Registry.get("Object")).doSomething();

这真的是很多代码。在 php 中,这将通过简单地完成:

Registry.foo.doSomething();

有什么办法可以让这更简单一点?我想我可以创建公共字段,但是注册表类需要隐式创建这些字段,因为可能需要添加注册表类本身未知的新对象,这很烦人:P

提前致谢!

4

3 回答 3

4

这是一个两方面的问题:

  1. Java 是一种静态类型语言,不提供在运行时定义对象的语言灵活性(您可以使用库在运行时合成类,但是,请参阅 #2)
  2. 对象的全局注册表破坏了类型安全语言中的许多安全性。如果您的整个应用程序以获取对象和将对象放入全局对象为中心Map,则可能会有更安全且耦合更少的设计。

如何解决?

  1. 重新设计您的应用程序结构以不需要全局地图。
  2. 使用 Java 的动态语言子集(例如 Groovy)。
  3. 使用 Scala 2.10(JVM 兼容),它具有Dynamic完全符合您要求的类型。
于 2012-12-15T02:42:57.787 回答
2

首先这个方法太冗长了:

public static Object get(String key) {
    if (Registry.box.get(key) != null) {
        return Registry.box.get(key);
    }else {
        return null;
    }
}

可能只是:

public static Object get(String key) {
   return Registry.box.get(key);
}

但其次,这绝对是一个糟糕的设计。全局存储库 - 听起来不合理。通过字符串键存储所有类型的对象 - 这太可怕了。

于 2012-12-15T02:46:36.460 回答
1

有什么办法可以让这更简单一点?

不是以任何实际的方式。Java 是一种静态类型语言,必须预先知道对象的结构。PHP 的等价物的想法__get__set该语言是对立的。

对于它的价值,无论如何,您的“注册表”看起来都是糟糕的设计。(诚​​然,从您展示的小代码中做出了一些非常疯狂的假设。)您不应该需要一个看似无关对象的全局存储库。您应该考虑某种依赖注入。

根据您的评论,而不是像这样构造您的代码:

class World implements GameSystem {

    public void update() {
        Registry.get("game").doSomething();
    }

}

你应该做:

class World implements GameSystem {

    Game game;
    public World(Game game) { // and other dependencies
        this.game = game;
    }

    public void update() {
        this.game.doSomething();
    }

}

这个想法是你的程序的组件实际上并没有任何业务知道如何找到其他组件。它还使组件之间的依赖关系显式化,并帮助您避免循环依赖关系。

于 2012-12-15T02:39:41.273 回答