考虑一个多人格斗游戏,客户端通过向服务器发送一个包含刚选择的战斗机名称的字符串来选择战斗机。

考虑服务器中的“战士”类结构:

Fighter
   Foo extends Fighter
   Bar extends Fighter
   Qux extends Fighter

例如客户端发送了这个"Bar"字符串,如何根据该字符串初始化子类?

我这样做的方式是像这样的enum:
public enum Champion {
    Foo {
        @Override
        public Fighter getNew() {
            return new Foo();
        }
    },

    Bar {
        @Override
        public Fighter getNew() {
            return new Bar();
        }
    },

    Qux {
        @Override
        public Fighter getNew() {
            return new Qux();
        }
    };

    public abstract Fighter getNew();

    public static boolean contains(String fighter) {
        for (Champion c : Champion.values()) {
            if (c.name().equals(fighter)) {
                return true;
            }
        }
        return false;
    }
}

然后我得到一个像这样的对象:
public Fighter getFighter(String fighterName) {
    if(Champion.contains(fighterName)) {
        return Champion.valueOf(fighterName).getNew();
    } else {
       return null;
    } // For example sake only :)
}

这是处理这种遭遇的正确方法吗?有没有更好的办法?我记得有一种已知的方式可以处理此类相遇,但无法确切记住哪种方式。
如果您有想法,请告诉我!

最佳答案

使用工厂,解决方案如下所示:

interface FighterFactory {
    Fighter create();
}

在外观中保留一个Map<String, FighterFactory>变量。每个Fighter类型都必须在其工厂图中注册。
private Map<String, FighterFactory> fighters;

public void register(String name, FighterFactory factory) {
  fighters.put(name, factory);
}

在每种Fighter类型中嵌入一个内部类Factory,例如
class Foo extends Fighter {

  //code for Foo

  public static class Factory implements FighterFactory {
    public Foo create() {
      return new Foo();
    }
  }
}

// and in your Facade

register("Foo", new Foo.Factory());

要实例化新的Fighter,请进入Fighter-Map并对其结果执行create。
FighterFactory factory = fighters.get(nameFromClient);
// null handling, if nameFromClient is not a Fighter type;
return factory.create();

与反射相比,此设计具有一些优点:
  • 这是安全的
  • 的create方法可以做的不仅仅是构造函数

  • 以及单一工厂方法(一种方法可处理所有Fighter类型):
  • (如果create方法变得比您对代码所做的更改更复杂(例如,用于创建实例的更多参数)位于Fighter类而非工厂方法。

  • 和枚举方法:
  • 使用的Enum唯一功能是遍历其值。保留值映射将用映射查找
  • 替换迭代
  • 位于战斗机附近而不是冠军枚举中的如何构造战斗机的信息
  • 您甚至可以确定FighterFactories是顶级类,而枚举内部类Factories则无法实现。
  • 10-06 07:15