This is not a discussion about whether Singleton is good or bad. It's about creating a singleton. The way I understand Singleton is that it is a class that should exist in most objects at all times. That is, if several classes instantiate a singleton at the same time, then they will use one instance of this singleton.
The problem with singleton is that once it is created, it will exist throughout the application. Using my method, you can create and delete Singleton garbage at any time if it is no longer in use. Well, I need to list (Singleton!) To create all the rest of Singleton. I think my method is reflection and serialized safe, but I'm not sure if there are any problems with the stream.
My method for creating singleton is as follows:
First, any class that wants to be singleton must extend the next class.
public abstract class Singleton {
public Singleton(SingletonFactory.SingletonParam singletonParam) {
if (singletonParam == null) {
throw new NullPointerException("singletonParam cannot be null)");
}
}
public abstract void destroy(SingletonFactory.SingletonParam singletonParam);
}
SingletonParam will be the inner class of an abstract class that cannot have an object that is SingletonParam in an instance of polymorphism meanings outside its container class.
This does not mean that subclasses extend the Singleton class at run time. This is for classes that are single, through a static instance. My method does not require a static instance of a singleton class.
Next class container
Note: after reading the answer from Stephen C, I made a change to initialize the HashMap from the constructor, and I do not understand why it is not a safe thread.
public enum SingletonFactory {
INSTANCE;
enum SingletonList {
A,
B,
......
}
private final HashMap<String, SingletonInfo> mfSingletonInfoHashMap = new HashMap<>();
SingletonFactory() {
mfSingletonInfoHasmap.put(A, final new SingletonInfo());
At this time the Singleton member of the SingletonInfo is null.
It will be instantiated when a class call getSingleton
}
private class SingletonInfo {
final Set callingObjects = new HashSet();
Singleton singleton;
}
public Object getSingleton(SingletonList inList, Object object) {
final SingletonInfo singletonInfo = mfSingletonInfoHashMap.get(inList);
synchronized (singletonInfo) {
if (singletonInfo.callingObjects.add(object)) {
if (singletonInfo.singleton == null) {
singletonInfo.singleton = createSingleton(singletonClassName);
}
} else {
throw new RuntimeException("getSingleton(" + singletonClassName + ") has already been called and not released");
}
return singletonInfo.singleton;
}
public void releaseSingleton(SingletonList inList, Object object) {
SingletonInfo singletonInfo = mfSingletonInfoHashMap.get(inList);
synchronized (singletonInfo) {
singletonInfo.callingObjects.remove(object);
if (singletonInfo.callingObjects.isEmpty()) {
singletonInfo.singleton.destroy(new SingletonParam() {
});
singletonInfo.singleton = null;
}
}
}
private Singleton createSingleton(SingletonList inList) {
switch(inList) {
case SingletonA:
return new SingletonA(new SingletonParam() {});
......
}
}
public abstract class SingletonParam {
private SingletonParam() {
}
}
}
, , HashSet, CallingObjects SingletonInfo, .
SingletonParam SingletonFactory, SingletonFactory.INSTANCE.getSingleton(you_singleton_class_name, this)