0

I am trying to achieve Singleton Instance with Abstract class in Java. I have read like implementing it as a LazyLoad is the best practice. I could not make it as I am not much used to this pattern and even Java.

  1. getInstance() is always null, I am not sure why?
  2. I don't think this follows lazy loading as the instance is constructed.
  3. Any additional comments are welcome apart from this as I am completely new to Java and worked on c# before.

Here is what I have,

Interface:

public interface IConditionAppender{
    public String Append();
}

Abstract

public abstract AppenderBase {

    private static IConditionAppender instance;

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

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

Implementation

public final class AndAppender extends AppenderBase implements IConditionAppender {

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

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

}

Test

System.out.println(AndAppender.getInstance().Append());
8
  • 1
    Where are you calling parametrized constructor of AppenderBase ? Commented Sep 14, 2018 at 9:23
  • @AshishkumarSingh, Sorry missed new keyword and it is constructed in AndAppender class Commented Sep 14, 2018 at 9:29
  • why is your AndAppender class constructor private? Commented Sep 14, 2018 at 9:55
  • 1
    With this design you cannot create OrAppender as the instance static field in AppenderBase will be replaced Commented Sep 14, 2018 at 9:56
  • 1
    Don't implement Singleton through inheritance as it uses static field and method which are not involved in late binding. You should implement Singleton for each And/OrOperation class Commented Sep 14, 2018 at 10:00

2 Answers 2

1

Here is how AndAppender can be implemented

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 ";
    }
}

The same approach for OrAppender etc.

Note: this implementation is not thread-safe.


A bit simpler way is to use Enum which is singleton by default and can implement interfaces.

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());

    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

private static final AndAppender instance = new AndAppender() works same right?
No. It's not lazy, an instance of AndAppender will be created at class loading time, not at first time it requested with getInstance() method
1

The code below may help you~

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);
        }
    }
}

From: https://www.cnblogs.com/wang9192/p/3975748.html

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.