您的位置:首页 > 其它

单例设计模式的分析(懒汉,饿汉式)

2017-03-07 09:53 127 查看
主要分析的是单例模式。包括懒汉式,饿汉式,登记式,以及懒汉式的改进型,
还有一个关于读取propertoes配置文件的实例。预计分为三节。这是第一节,先分析最简单的懒汉式和饿汉式。

单例模式是设计模式中比较简单的一种。适合于一个类只有一个实例的情况,比如窗口管理器,打印缓冲池和文件系统,
它们都是原型的例子。典型的情况是,那些对象的类型被遍及一个软件系统的不同对象访问,因此需要一个全局的访问
指针,这便是众所周知的单例模式的应用。当然这只有在你确信你不再需要任何多于一个的实例的情况下。
单例模式的用意在于前一段中所关心的。通过单例模式你可以:

一、确保一个类只有一个实例被建立
二、提供了一个对对象的全局访问指针
三、在不影响单例类的客户端的情况下允许将来有多个实例

经典的单例模式有三种,懒汉式、饿汉式和 登记式。

懒汉式的特点是延迟加载,比如配置文件,采用懒汉式的方法,顾名思义,懒汉么,很懒的,配置文件的实例直到用到的
时候才会加载。。。。。。

饿汉式的特点是一开始就加载了,如果说懒汉式是“时间换空间”,那么饿汉式就是“空间换时间”,因为一开始就创建了实例,所以每次用到的之后直接返回就好了。

让我们先看下代码:

懒汉式:

[java]
view plain
copy
print?

//懒汉式单例模式

public
class MySingleton {

//设立静态变量

private
static MySingleton mySingleton =
null;

private MySingleton(){

//私有化构造函数

System.out.println("-->懒汉式单例模式开始调用构造函数");

}

//开放一个公有方法,判断是否已经存在实例,有返回,没有新建一个在返回

public
static MySingleton getInstance(){

System.out.println("-->懒汉式单例模式开始调用公有方法返回实例");

if(mySingleton ==
null){

System.out.println("-->懒汉式构造函数的实例当前并没有被创建");

mySingleton = new MySingleton();

}else{

System.out.println("-->懒汉式构造函数的实例已经被创建");

}
System.out.println("-->方法调用结束,返回单例");

return mySingleton;

}
}



//懒汉式单例模式
public class MySingleton {

//设立静态变量
private static MySingleton mySingleton = null;

private MySingleton(){
//私有化构造函数
System.out.println("-->懒汉式单例模式开始调用构造函数");
}

//开放一个公有方法,判断是否已经存在实例,有返回,没有新建一个在返回
public static MySingleton getInstance(){
System.out.println("-->懒汉式单例模式开始调用公有方法返回实例");
if(mySingleton == null){
System.out.println("-->懒汉式构造函数的实例当前并没有被创建");
mySingleton = new MySingleton();
}else{
System.out.println("-->懒汉式构造函数的实例已经被创建");
}
System.out.println("-->方法调用结束,返回单例");
return mySingleton;
}
}
看下客户端的测试代码:

[java]
view plain
copy
print?

public
class Client {

/**

* 懒汉式单例模式

* MySingleton

*/

public
static
void myprint(){

System.out.println("-----------------懒汉式单例模式----------------");

System.out.println("第一次取得实例(懒汉式)");

MySingleton s1 = MySingleton.getInstance();
System.out.println("第二次取得实例(懒汉式)");

MySingleton s2 = MySingleton.getInstance();
if(s1==s2){

System.out.println(">>>>>s1,s2为同一实例(懒汉式)<<<<<");

}
System.out.println();
}
/**

* @param args

*/

public
static
void main(String[] args) {

// TODO Auto-generated method stub

//懒汉式

myprint();
//饿汉式

//myprint2();

//懒汉式改进

//myprint2a();

//登记式

//myprint3();

}

}



public class Client {

/**
* 懒汉式单例模式
* MySingleton
*/
public static void myprint(){
System.out.println("-----------------懒汉式单例模式----------------");
System.out.println("第一次取得实例(懒汉式)");
MySingleton s1 = MySingleton.getInstance();
System.out.println("第二次取得实例(懒汉式)");
MySingleton s2 = MySingleton.getInstance();
if(s1==s2){
System.out.println(">>>>>s1,s2为同一实例(懒汉式)<<<<<");
}
System.out.println();
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//懒汉式
myprint();
//饿汉式
//myprint2();
//懒汉式改进
//myprint2a();
//登记式
//myprint3();

}

}

输出结果为:

-----------------懒汉式单例模式----------------

第一次取得实例(懒汉式)

-->懒汉式单例模式开始调用公有方法返回实例

-->懒汉式构造函数的实例当前并没有被创建

-->懒汉式单例模式开始调用构造函数

-->方法调用结束,返回单例

第二次取得实例(懒汉式)

-->懒汉式单例模式开始调用公有方法返回实例

-->懒汉式构造函数的实例已经被创建

-->方法调用结束,返回单例

>>>>>s1,s2为同一实例(懒汉式)<<<<<

可以看出,在第一次调用公有方法的时候,并没有实例,所以我们创建了一个实例,之后再访问的时候,因为已经有一个已经创建好的实例,所以直接返回了。

饿汉式:

[java]
view plain
copy
print?

//饿汉式单例模式

public
class MySingleton2 {

//设立静态变量,直接创建实例

private
static MySingleton2 mySingleton =
new MySingleton2();

private MySingleton2(){

//私有化构造函数

System.out.println("-->饿汉式单例模式开始调用构造函数");

}

//开放一个公有方法,判断是否已经存在实例,有返回,没有新建一个在返回

public
static MySingleton2 getInstance(){

System.out.println("-->饿汉式单例模式开始调用公有方法返回实例");

return mySingleton;

}
}



//饿汉式单例模式
public class MySingleton2 {

//设立静态变量,直接创建实例
private static MySingleton2 mySingleton = new MySingleton2();

private MySingleton2(){
//私有化构造函数
System.out.println("-->饿汉式单例模式开始调用构造函数");
}

//开放一个公有方法,判断是否已经存在实例,有返回,没有新建一个在返回
public static MySingleton2 getInstance(){
System.out.println("-->饿汉式单例模式开始调用公有方法返回实例");
return mySingleton;
}
}

看下客户端的测试代码:

[java]
view plain
copy
print?

/**

* 饿汉式单例模式

* MySingleton2

*/

public
static
void myprint2(){

System.out.println("-----------------饿汉式单例模式----------------");

System.out.println("第一次取得实例(饿汉式)");

MySingleton2 s1 = MySingleton2.getInstance();
System.out.println("第二次取得实例(饿汉式)");

MySingleton2 s2 = MySingleton2.getInstance();
if(s1==s2){

System.out.println(">>>>>s1,s2为同一实例(饿汉式)<<<<<");

}
System.out.println();
}



/**
* 饿汉式单例模式
* MySingleton2
*/
public static void myprint2(){
System.out.println("-----------------饿汉式单例模式----------------");
System.out.println("第一次取得实例(饿汉式)");
MySingleton2 s1 = MySingleton2.getInstance();
System.out.println("第二次取得实例(饿汉式)");
MySingleton2 s2 = MySingleton2.getInstance();
if(s1==s2){
System.out.println(">>>>>s1,s2为同一实例(饿汉式)<<<<<");
}
System.out.println();
}


[java]
view plain
copy
print?

/**

* @param args

*/

public
static
void main(String[] args) {

// TODO Auto-generated method stub

//懒汉式

//myprint();

//饿汉式

myprint2();
//懒汉式改进

//myprint2a();

//登记式

//myprint3();

}



/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//懒汉式
//myprint();
//饿汉式
myprint2();
//懒汉式改进
//myprint2a();
//登记式
//myprint3();

}


输出结果为:

-----------------饿汉式单例模式----------------

第一次取得实例(饿汉式)

-->饿汉式单例模式开始调用构造函数

-->饿汉式单例模式开始调用公有方法返回实例

第二次取得实例(饿汉式)

-->饿汉式单例模式开始调用公有方法返回实例

>>>>>s1,s2为同一实例(饿汉式)<<<<<

总结一下,两种方案的构造函数和公用方法都是静态的(static),实例和公用方法又都是私有的(private)。但是饿汉式每次调用的时候不用做创建,直接返回已经创建好的实例。这样虽然节省了时间,但是却占用了空间,实例本身为static的,会一直在内存中带着。懒汉式则是判断,在用的时候才加载,会影响程序的速度。最关键的是,在并发的情况下,懒汉式是不安全的。如果两个线程,我们称它们为线程1和线程2,在同一时间调用getInstance()方法,如果线程1先进入if块,然后线程2进行控制,那么就会有两个实例被创建。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  设计模式