java - 从字符串初始化子类对象

标签 java design-patterns

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

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

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 type 必须在此映射中使用其 Factory 注册。

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 并在其结果上执行创建。

FighterFactory factory = fighters.get(nameFromClient);
// null handling, if nameFromClient is not a Fighter type;
return factory.create();

这种设计比反射有一些优势:

  • 它是安全的
  • create 方法可以做的不仅仅是构造函数

以及单一工厂方法(一个方法处理所有 Fighter 类型):

  • 如果创建方法变得比您对代码的更改位于 Fighter 类而不是工厂方法更复杂(例如,创建实例的参数更多)。

以及枚举方法:

  • 使用的枚举的唯一特性是迭代它的值。保留一个 Map 的值代替迭代与 Map 查找
  • 关于如何构建战斗机的信息位于战斗机附近,而不是在冠军枚举中
  • 您甚至可以决定 FighterFactories 是顶级类,这是枚举内部类工厂无法做到的。

关于java - 从字符串初始化子类对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32086139/

相关文章:

java - 将数组分成相等大小,使得给定函数的值最小

java - 从外部目录加载属性文件

programming-languages - 展示编程语言之间差异的典型任务/问题

Silverlight 异步设计模式问题

java - 无法连接到ARServer

java - 从 Java 类(或相反)生成 XML 模式

Java 字符串 ReplaceAll 和 ReplaceFirst 在替换文本的 $ 符号处失败

c++ - 重构厚客户端遗留应用程序

oop - 存储库模式与简单数据访问层有何不同?

java - 带线程的观察者模式