【问题标题】:Java Lazy Load Singleton in Abstract Class抽象类中的 Java 延迟加载单例
【发布时间】:2018-09-14 09:19:30
【问题描述】:

我正在尝试用 Java 中的抽象类实现单例实例。我读过喜欢将其实现为 LazyLoad 是最佳实践。我做不到,因为我不太习惯这种模式甚至 Java。

  1. getInstance() 总是为空,我不知道为什么?
  2. 我不认为这是在构造实例时遵循延迟加载。
  3. 除此之外,欢迎任何其他 cmets,因为我是 Java 的新手,之前使用过 c#。

这就是我所拥有的,

界面:

public interface IConditionAppender{
    public String Append();
}

摘要

public abstract AppenderBase {

    private static IConditionAppender instance;

    protected AppenderBase(IConditionAppender instance)
    {
         this.instance = instance;
    }

    public static IConditionAppender getInstance(){ return instance; }
}

实施

public final class AndAppender extends AppenderBase implements IConditionAppender {

private AndAppender()
{
    super(new AndAppender())
}

@Override
public String Append()
{
    return " AND ";
}

}

测试

System.out.println(AndAppender.getInstance().Append());

【问题讨论】:

  • 你在哪里调用AppenderBase的参数化构造函数?
  • @AshishkumarSingh,抱歉错过了新关键字,它是在 AndAppender 类中构造的
  • 为什么你的 AndAppender 类构造函数是私有的?
  • 使用这种设计,您无法创建OrAppender,因为AppenderBase 中的instance 静态字段将被替换
  • 不要通过继承实现 Singleton,因为它使用了后期绑定不涉及的静态字段和方法。您应该为每个 And/OrOperation 类实现 Singleton

标签: java singleton lazy-loading


【解决方案1】:

这是AndAppender 的实现方式

public final class AndAppender implements ConditionAppender {
    private static final AndAppender instance;
    public static AndAppender getInstance() {
        if (instance == null)
            instance = new AndAppender();
        return instance;
    }

    private AndAppender() { }

    @Override
    public String append() {
        return " AND ";
    }
}

OrAppender 等的方法相同。

注意:此实现不是线程安全的。


更简单一点的方法是使用Enum,默认是单例的,可以实现接口。

public enum  Appender implements ConditionAppender {
    AND(" AND "), OR(" OR ");

    final String operation;

    Appender(String operation) {
        this.operation = operation;
    }

    @Override
    public String append() {
        return operation;
    }

    public static void main(String[] args) {
        System.out.println(AND.append());
        System.out.println(OR.append());

    }
}

【讨论】:

  • private static final AndAppender instance = new AndAppender() 工作正常吗?
  • 没有。这不是惰性AndAppender 的实例将在类加载时创建,而不是在第一次使用getInstance() 方法请求时创建
【解决方案2】:

下面的代码可以帮到你~

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-13
    • 1970-01-01
    • 1970-01-01
    • 2011-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多