设计模式 - 基于枚举类型创建对象的 Java 方法



我的类是这样的:

class X {}
class Y extends X {};
class Z extends X {};

我为每个子类(id + 类)都有一个枚举:

enum Type {
   Y_TYPE(1, Y.class), Z_TYPE(2, Z.class);
   int id;
   Class c;
   public Type(int id, Class c) { this.id = id; this.c = c; }
   public static X createInstance() throws Exception {
      return c.newInstance();
   }
}

然后我按如下方式使用它们:

X parseFromID(int id) {
   for (Type v : Type.values()) {
     if (v.id == id) {
        return v.createInstance();
     }
   }
}

它工作正常,但我想知道这是否是一种基于整数 id 创建数据的 Java 主义方式?有什么不好的事情应该寻找吗?

有没有办法强制传入的类是 X 类型,而没有冗长的 if-else 条件?想想当我有大量的子类时。


为什么要处理整数 ID?

正在编写某种解析器,所以我需要将我从某处获取的整数 id 转换为适当的对象。

这里真的没有理由使用反射。抛出异常也是一种不好的做法,如果不使用反射,则不必处理反射异常。你可以简单地做

enum Type {
    Y_TYPE(1) {
        @Override
        public X createInstance() {
            return new Y();
        }
    }, Z_TYPE(2) {
        @Override
        public X createInstance() {
            return new Z();
        }
    };
    private int id;
    private Type(int id) { 
        this.id = id; 
    }
    public abstract X createInstance();
}

这也很有用,因为它不会强制每个子类都有一个公共的 no-arg 构造函数,并且如果可能的话,还允许返回相同的 X 或 Y 实例。

如果您担心匿名类定义的冗长性,如果您使用的是 Java 8,则可以将它们替换为 lambda:

import java.util.function.Supplier;
enum Type {
    Y_TYPE(1, X::new), Z_TYPE(2, Y::new);
    private int id;
    private Supplier<X> supplier;
    private Type(int id, Supplier<X> supplier) {
        this.id = id;
        this.supplier = supplier;
    }
    public X createInstance() {
        return supplier.get();
    }
}

使用工厂和地图更具学术性:

import java.util.HashMap;
import java.util.Map;
interface Factory<T> {
    T createInstance();
}
class X {/**/}
class Y extends X {/**/}
class Z extends X {/**/}
class Factories {
   static Map<Integer, Factory<?>> factories = new HashMap<>();
   static {
      factories.put( 1, X::new );
      factories.put( 2, Y::new );
      factories.put( 3, Z::new );
   }
   @SuppressWarnings("unchecked")
   static <T> Factory<T> get( int id ) {
      return (Factory<T>)factories.get( id );
   }
}
public class Main {
   static void main( String[] args ) {
      final Factory<X> fx = Factories.get( 1 );
      final X x = fx.createInstance();
      final Factory<Y> fy = Factories.get( 2 );
      final Y y = fy.createInstance();
      final Factory<Z> fz = Factories.get( 3 );
      final Z z = fz.createInstance();
   }
}

有没有办法强制传入的类是 X 类型,而没有冗长的 if-else 条件?

是的,您可以使用泛型来限制类。 将构造函数更改为:

public Type(int id, Class<? extends X> c) { this.id = id; this.c = c; }

为什么要处理整数 ID?您可以直接使用枚举值,也可以(如果需要传输或存储它们)使用它们的字符串表示形式,并在需要时使用枚举的 valueOf 方法解析字符串。

相关内容

  • 没有找到相关文章

最新更新