先看下标准的单例模式之一的代码写法,单例模式有几种写法,如下:
public class SocketUtil {
private static volatile SocketUtil socketUtil;
/**
* socketUtil 单例模式 - 双重校验锁
*/
public static SocketUtil getInstance() {
if (socketUtil == null) {
synchronized (SocketUtil.class) {
if (socketUtil == null) {
socketUtil = new SocketUtil();
}
}
}
return socketUtil;
}
private SocketUtil() {
}
}
构造函数为私有的,那么其他地方就不能再生产多的实例,保证了进程中实例的唯一性;
but, 我看了几个目前安卓端github上最火的轮子Glide、EventBus的源码,发现它们并没有把构造函数私有化,总不能说大佬连最基本的单例都不懂吧,我就纳闷了,上代码为证:
Glide:
/**
* A singleton to present a simple static interface for building requests with
* {@link RequestBuilder} and maintaining an {@link Engine}, {@link BitmapPool},
* {@link com.bumptech.glide.load.engine.cache.DiskCache} and {@link MemoryCache}.
*/
public class Glide implements ComponentCallbacks2 {
private static final String DEFAULT_DISK_CACHE_DIR = "image_manager_disk_cache";
private static final String TAG = "Glide";
private static volatile Glide glide;
private static volatile boolean isInitializing;
/**
* Get the singleton.
*
* @return the singleton
*/
@NonNull
public static Glide get(@NonNull Context context) {
if (glide == null) {
synchronized (Glide.class) {
if (glide == null) {
checkAndInitializeGlide(context);
}
}
}
return glide;
}
Glide(
@NonNull Context context,
@NonNull Engine engine,
@NonNull MemoryCache memoryCache,
@NonNull BitmapPool bitmapPool,
@NonNull ArrayPool arrayPool,
@NonNull RequestManagerRetriever requestManagerRetriever,
@NonNull ConnectivityMonitorFactory connectivityMonitorFactory,
int logLevel,
@NonNull RequestOptions defaultRequestOptions,
@NonNull Map<Class<?>, TransitionOptions<?, ?>> defaultTransitionOptions) {
this.engine = engine;
this.bitmapPool = bitmapPool;
this.arrayPool = arrayPool;
this.memoryCache = memoryCache;
this.requestManagerRetriever = requestManagerRetriever;
……
}
}
EventBus:
/**
* EventBus is a central publish/subscribe event system for Android. Events are posted ({@link #post(Object)}) to the
* bus, which delivers it to subscribers that have a matching handler method for the event type. To receive events,
* subscribers must register themselves to the bus using {@link #register(Object)}. Once registered, subscribers
* receive events until {@link #unregister(Object)} is called. Event handling methods must be annotated by
* {@link Subscribe}, must be public, return nothing (void), and have exactly one parameter
* (the event).
*
* @author Markus Junginger, greenrobot
*/
public class EventBus {
/** Log tag, apps may override it. */
public static String TAG = "EventBus";
static volatile EventBus defaultInstance;
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
/** Convenience singleton for apps using a process-wide EventBus instance. */
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
/**
* Creates a new EventBus instance; each instance is a separate scope in which
events are delivered. To use a
* central bus, consider {@link #getDefault()}.
*/
public EventBus() {
this(DEFAULT_BUILDER);
}
}
再看看jdk中的Runtime这个类的代码,构造方法私有化了,如下:
public class Runtime {
private static Runtime currentRuntime = new Runtime();
/**
* Returns the runtime object associated with the current Java application.
* Most of the methods of class <code>Runtime</code> are instance
* methods and must be invoked with respect to the current runtime object.
*
* @return the <code>Runtime</code> object associated with the current
* Java application.
*/
public static Runtime getRuntime() {
return currentRuntime;
}
/** Don't let anyone else instantiate this class */
private Runtime() {}
}
哈哈,到底该不该私有化呢?
此问题令小弟夜不能寐,以前一直写单例都没思考过这个问题,最后请教了几个大神,我得出以下结论:
标准的单例模式,构造函数是需要私有化的,但是单例模式是一种思想,代码模式设计的目的是为了服务于业务的,可能某些特俗场景下,需要外界使用构造函数。
好了,请路过的大神多多指点迷津,不胜感激!