2

我创建了两个enum单例类:

public enum A {
    INSTANCE;

    public void init(param p1, param p2) {
    }

    public void connect() {
    }

    public void disconnect() {
    }

    public bool isConnected() {
    }
}

public enum B {
    INSTANCE;

    public void init(param p1) {
    }

    public void connect() {
    }

    public void disconnect() {
    }

    public bool isConnected() {
    }
}

如您所见,这两个枚举类非常相似,所以我想知道是否应该创建某种基本抽象类/枚举或接口,然后让这两个枚举从中扩展或实现。

更新1:我想把一些共享成员变量放在基类上

更新 2:我应该改变定义单例的方式吗?

4

4 回答 4

2

根据java枚举教程

所有枚举都隐式扩展 java.lang.Enum。由于 Java 不支持多重继承,因此枚举不能扩展其他任何东西。

这是与此主题相关的有趣的SO 讨论。

于 2013-04-19T20:05:35.703 回答
2

正如 Nambari 所说,你不能让枚举扩展任何东西。然而,他们忽略了说的是你可以让一个枚举实现一个接口,这与使用 implements 关键字的类一样。我在工作中做过这个,它在正确的情况下非常有用!这里有一个例子:http: //javahowto.blogspot.co.uk/2008/04/java-enum-examples.html

于 2013-04-19T20:17:31.467 回答
0

Heinz KabutzDynamicObjectAdapterFactory发布了一个可爱的小类,它使用泛型和反射来调整对象以实现接口,方法是为对象提供已经实现接口的源类。

像下面这样使用它,您可以将您的代理包装INSTANCE在代理中。当然,生成的对象不再是一个,enum但它确实保留了enum我认为的所有单一性。显然,它也可以使用任何对象来实现您的界面。

enum我认为这与扩展课程一样接近。

这是一些似乎有效的测试代码。显然该对象不再是一个,enum但由于您的目标是一个单例,这可能是可以接受的。

public class Test {
  // To implement this.
  public interface Implement {
    public void init();

    public void connect();

    public void disconnect();

    public boolean isConnected();
  }

  // An implementor that does implement.
  public static class Implements implements Implement {

    @Override
    public void init() {
    }

    @Override
    public void connect() {
    }

    @Override
    public void disconnect() {
    }

    @Override
    public boolean isConnected() {
      return false;
    }
  }

  // Extend the INSTANCE in this.
  public enum Extend {
    INSTANCE;
    // Hold my adapted version - thus still a singleton.
    public final Implement adaptedInstance;

    Extend () {
      // Use the constructor to adapt the instance.
      adaptedInstance = DynamicObjectAdapterFactory.adapt(this, Implement.class, new Implements());
    }
  }

  // Provides an INSTANCE that has been extended by an Implements to implement Implement.
  public static Implement getInstance () {
    return Extend.INSTANCE.adaptedInstance;
  }

  public void test() {
    System.out.println("Hello");
    Implement i = getInstance();

  }

  public static void main(String args[]) {
    new Test().test();
  }
}

这是 DynamicObjectAdapterFactory - 我已经对原来的它进行了一些调整 - 我希望 Kabutz 博士不会反对。

public class DynamicObjectAdapterFactory {
  // Use methods in adaptee unless they exist in target in which case use adapter.
  // Implement target in passing.
  public static <T> T adapt(final Object adaptee,
                            final Class<T> target,
                            final Object adapter) {

    return (T) Proxy.newProxyInstance(
            Thread.currentThread().getContextClassLoader(),
            new Class[]{target},
            new InvocationHandler() {
      private final String name =
              adaptee.getClass().getSimpleName() + "(" + adaptee.toString() + ")"
              + "+" + adapter.getClass().getSimpleName() + "(" + adapter.toString() + ")";
      // The methods I wish to adapt.
      private Map<MethodIdentifier, Method> adaptedMethods = new HashMap<>();

      {
        // initializer block - find all methods in adapter object
        Method[] methods = adapter.getClass().getDeclaredMethods();
        for (Method m : methods) {
          // Keep a map of them.
          adaptedMethods.put(new MethodIdentifier(m), m);
        }
      }

      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
          // Has it been adapted?
          Method otherMethod = adaptedMethods.get(new MethodIdentifier(method));
          if (otherMethod != null) {
            return otherMethod.invoke(adapter, args);
          } else {
            return method.invoke(adaptee, args);
          }
        } catch (InvocationTargetException e) {
          throw e.getTargetException();
        }
      }

      @Override
      public String toString() {
        StringBuilder s = new StringBuilder();
        // Really simple. May get more flexible later.
        s.append("Adapted: ").append(name);
        return s.toString();
      }
    });
  }

  private static class MethodIdentifier {
    private final String name;
    private final Class[] parameters;

    public MethodIdentifier(Method m) {
      name = m.getName();
      parameters = m.getParameterTypes();
    }

    @Override
    public boolean equals(Object o) {
      // I am always equal to me.
      if (this == o) {
        return true;
      }
      // I cannot be equal to something of a different type.
      if (!(o instanceof MethodIdentifier)) {
        return false;
      }
      MethodIdentifier mid = (MethodIdentifier) o;
      return name.equals(mid.name) && Arrays.equals(parameters, mid.parameters);
    }

    @Override
    public int hashCode() {
      return name.hashCode();
    }
  }
}
于 2013-04-19T21:59:23.397 回答
0

您可以将下面的抽象类用于单例而不是枚举。

public abstract class AbstractSingleton {

    private static Map<String, AbstractSingleton> registryMap = new HashMap<String, AbstractSingleton>();

    AbstractSingleton() throws SingletonException {
        String clazzName = this.getClass().getName();
        if (registryMap.containsKey(clazzName)) {
            throw new SingletonException("Cannot construct instance for class " + clazzName + ", since an instance already exists!");
        } else {
            synchronized (registryMap) {
                if (registryMap.containsKey(clazzName)) {
                    throw new SingletonException("Cannot construct instance for class " + clazzName + ", since an instance already exists!");
                } else {
                    registryMap.put(clazzName, this);
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    public static <T extends AbstractSingleton> T getInstance(final Class<T> clazz) throws InstantiationException, IllegalAccessException {
        String clazzName = clazz.getName();
        if (!registryMap.containsKey(clazzName)) {
            synchronized (registryMap) {
                if (!registryMap.containsKey(clazzName)) {
                    T instance = clazz.newInstance();
                    return instance;
                }
            }
        }
        return (T) registryMap.get(clazzName);
    }

    public static AbstractSingleton getInstance(final String clazzName)
            throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        if (!registryMap.containsKey(clazzName)) {
            Class<? extends AbstractSingleton> clazz = Class.forName(clazzName).asSubclass(AbstractSingleton.class);
            synchronized (registryMap) {
                if (!registryMap.containsKey(clazzName)) {
                    AbstractSingleton instance = clazz.newInstance();
                    return instance;
                }
            }
        }
        return registryMap.get(clazzName);
    }

    @SuppressWarnings("unchecked")
    public static <T extends AbstractSingleton> T getInstance(final Class<T> clazz, Class<?>[] parameterTypes, Object[] initargs)
            throws SecurityException, NoSuchMethodException, IllegalArgumentException,
            InvocationTargetException, InstantiationException, IllegalAccessException {
        String clazzName = clazz.getName();
        if (!registryMap.containsKey(clazzName)) {
            synchronized (registryMap) {
                if (!registryMap.containsKey(clazzName)) {
                    Constructor<T> constructor = clazz.getConstructor(parameterTypes);
                    T instance = constructor.newInstance(initargs);
                    return instance;
                }
            }
        }
        return (T) registryMap.get(clazzName);
    }

    static class SingletonException extends Exception {
        private static final long serialVersionUID = -8633183690442262445L;

        private SingletonException(String message) {
            super(message);
        }
    }
}

来自:https ://www.cnblogs.com/wang9192/p/3975748.html

于 2019-04-10T11:59:25.347 回答