我创建了两个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:我应该改变我定义单身人士的方式吗?
答案 0 :(得分:2)
所有枚举都隐式扩展了java.lang.Enum。既然Java没有 支持多重继承,枚举不能扩展任何其他内容。
以下是与此主题相关的有趣SO discussion。
答案 1 :(得分:2)
正如Nambari所说,你无法扩展任何内容。然而,他们忽略的是你可以使用enum实现一个接口,这与使用implements关键字的类一样。我在工作中做到了这一点,它在正确的情况下非常有用!这里有一个例子:http://javahowto.blogspot.co.uk/2008/04/java-enum-examples.html
答案 2 :(得分:0)
Heinz Kabutz发布了一个名为DynamicObjectAdapterFactory
的可爱小类,它使用泛型和反射来调整对象以实现接口,方法是为其提供已实现接口的源类。 / p>
如下所示,您可以将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();
}
}
}
答案 3 :(得分: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);
}
}
}