单例模式(Singleton)
单例模式是对象的创建模式,单例模式能够确保某个类只有一个单一的实例对象存在,同时能够自行实例化并将单一的实例提供给外界调用的特点,其在实际项目开发中经常被用到。
单例模式的结构图说明如下:
结合上面的模式结构说明图,我们可以看到单例模式有几个显著的特点,具体如下所示:
A、单例类(Singleton)只能有一个唯一的实例存在。
B、单例类必须有能够自行创建自己的实例对象的能力。
C、单例类必须能够给外界其他对象提供这个实例。
另外,对于单例模式从产生到现在,也已经有了几种形式,下面我们就介绍几种常用到的形式(以代码的形式说明):
第一种形式:
/*
* 单例模式---形式1
*/
public
class SingletonA {
private
static final SingletonA instance =
new SingletonA();
/* 私有构造子*/
private SingletonA() {
// CODE
}
/* 供外部调用的实例方法*/
public
static SingletonA getInstance(){
return instance;
}
}
第二种形式:
/*
* 单例模式---形式2
*/
public
class SingletonB {
private
static SingletonB instance =
null;
/* 私有构造子*/
private SingletonB() {
// CODE
}
/* 供外部调用的实例方法*/
public
static SingletonB getInstance() {
if(null ==
instance) {
instance = new SingletonB();
}
return instance;
}
}
第三种形式:
/*
* 单例模式---形式3
*/
public
class SingletonC {
private
static SingletonC instance =
null;
/* 私有构造子*/
private SingletonC() {
// CODE
}
/* 供外界调用的实例方法 这里用到了同步*/
public
static synchronized SingletonC getInstance() {
if(null ==
instance) {
instance =
new SingletonC();
}
return instance;
}
}
当然,在这里我只列出了比较常见到的几种形式的单例,下面来具体的分析下他们之间的联系和区别,并在最后举个实际的例子来使用单例模式。具体如下所示:
对于形式1的单例模式的特点就是在单例类自己被加载的时候就将自己实例化了。但从资源的利用率角度看的话,这种方式的实现会差一点;而第二种形式的单例模式是对第一种形式的小缺点做了优化,即在加载器加载单例类时不选择创建实例对象,只有在真正需要这个单例的时候才去创建唯一的实例;如果从时间和反应的速度看的话,那么形式1的单例要比形式2的要快些。对于形式3的单例,由于它使用了同步的机制,这样势必会降低它的性能,有利也有弊,它能够很好的在异步线程中保证实例的唯一性。
总的来说,形式1和形式2更符合Java机制,就我个人习惯于第二种形式的单例模式。下面具体举个例子来说明单例的使用,当然我使用自己习惯的单例模式形式。例子是这样的,在实际项目当中,我么会经常的要获取移动设备的屏幕宽和高,那么为了便于管理和统一,我们一般选择将获取宽和高的方法封装在一个单一的类中,同时为了避免重复的创建这个类,我们选择单例模式来实现。我的代码如下:
单例模式:
/* 单例类*/
public
class PhoneUtil {
private
static PhoneUtil instance =
null;
private
static Context context =
null;
/* 私有的构造子*/
private PhoneUtil(Context ctx) {
context = ctx;
}
/* 供外部调用的实例化方法 保证创建唯一的实例对象*/
public
static PhoneUtil getInstance(Contextctx) {
if(null ==
instance) {
instance =
new PhoneUtil(ctx);
}
return instance;
}
/* 获得屏幕的宽度*/
public
int getScreenWidth() {
Display display = ((WindowManager)
context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
return display.getWidth();
}
/* 获得屏幕的高度*/
public
int getScreenHeight() {
Display display = ((WindowManager)
context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
return display.getHeight();
}
}
前端调用:
public
class SingletonActivity extends Activity {
private
static String TAG =
"SingletonActivity";
@Override
protected
void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_singleton);
int screenWidth = PhoneUtil.getInstance(this).getScreenWidth();
log("the screen width:" + screenWidth);
int screenHeight = PhoneUtil.getInstance(this).getScreenHeight();
log("the screen height:" + screenHeight);
}
private
void log(String log) {
Log.d(TAG, log);
}
}
代码的运行效果:
从上面的图,我的手机的屏幕宽和高分别为320和480,看来分辨率和屏幕小的可怜了!
好了,到这里我们基本分析和使用了常用的单例模式。
技术交流群:179914858