您的位置:首页 > 其它

设计模式初探-单例模式(Singleton)

2014-03-05 10:25 295 查看
Singleton模式,又称单例模式,它保证一个类仅有一个实例,并提供一个访问它的全局访问点。单例模式在平常开发中经常用到,比如系统的全局配置属性,常用的工具类或工厂方法都可以实现为一个单例。单例模式概念很简单,实现起来也不麻烦,但一不小心还是有可能出错的。

一、使用场景

只要是要求实例唯一的都可以使用单例模式来实现,特别是耗资源的实例!

二、UML图



三、Java实现

1、懒汉型

[java] view
plaincopy





package study.patterns.singleton;

/**

* 单例模式:根据实例创建的时机与方式可分为

* 懒汉型,饿汉型,双重检测型等

* @author qbg

*

*/

public class Singleton {

private static Singleton instance = null;

/*

* 限制客户自己生成类实例的能力,不过通过java反射机制可以突破此限制

*/

/**

* 为用户提供统一的获取类实例的接口,

* 此接口可以根据需求改变实现,即可以保持类实例的唯一,

* 也可以维持多个类实例,这对用户来说是透明的。

* @return

*/

public static synchronized Singleton getInstance(){

if(instance==null){

instance = new Singleton();

}

return instance;

}

}

通过将instance暴露为public的静态的类属性也可以实现单例模式,但较工厂方法相比缺少灵活性,比如后期单例变多例。同时,由于静态类属性是通过类加载器保证实例的唯一性(instance在类装载时才会实例化),而类装载的时机有很多种,导致对实例的创建缺乏掌控。

懒汉型单例由于延迟了类实例的创建,只在真正需要时才创建,所以较饿汉型更适用,当然如果不需要考虑实例的懒加载那就无所谓了。对于耗资源,费时间的实例创建最好采用懒汉形式实现。

2、饿汉型

[java] view
plaincopy





package study.patterns.singleton;

/**

* 单例模式:根据实例创建的时机与方式可分为

* 懒汉型,饿汉型,双重检测型等

* @author qbg

*

*/

public class Singleton {

/**

* 这种方式基于classloder机制避免了多线程的同步问题,

* 不过,instance在类装载时就实例化,而导致类装载的原因有很多种。

* 在单例模式中大多数都是调用getInstance方法, 但不排除其他方式(比如调用其他的静态方法)导致类装载。

*/

private static Singleton instance = new Singleton();

/*

* 限制客户自己生成类实例的能力,不过通过java反射机制可以突破此限制

*/

private Singleton(){}

/**

* 为用户提供统一的获取类实例的接口,

* 此接口可以根据需求改变实现,即可以保持类实例的唯一,

* 也可以维持多个类实例,这对用户来说是透明的。

* 由于类加载器机制避免线程同步问题,所以此处不需要再同步了

* @return

*/

public static Singleton getInstance(){

return instance;

}

}

3、双重检测型

[java] view
plaincopy





package study.patterns.singleton;

/**

* 单例模式:根据实例创建的时机与方式可分为

* 懒汉型,饿汉型,双重检测型等

* @author qbg

*

*/

public class Singleton {

private static Singleton instance = null;

/*

* 限制客户自己生成类实例的能力,不过通过java反射机制可以突破此限制

*/

/**

* 双重检测机制,确保懒加载又提高了性能。

* @return

*/

public static Singleton getInstance(){

//先判断实例是否创建好了,如果好了直接返回

if(instance == null){

//如果实例没有创建好则同步实例创建过程.

synchronized (Singleton.class) {

if(instance==null){

instance = new Singleton();

}

}

}

return instance;

}

}

双重检测机制由于将同步过程最小化,且尽可能的减少同步次数,从而提高了性能。第一种实现方式每次通过getInstance()获取实例都需要同步,而这些同步只需在实例创建时才有用,大大浪费资源。不过双重检测机制在java 5后才能表现正确的行为,参考http://www.ibm.com/developerworks/cn/java/j-dcl.html

4、枚举型

[java] view
plaincopy





package study.patterns.singleton;

/**

* 利用java 1.5提供的枚举类型实现单例。

* 此方式较其他实现方式更简洁,由于枚举无偿地提供序列化机制,

* 绝对防止多次实例化,即使是在面向复杂的序列化或反射攻击的时候。

* 不过这种方式只能在java 1.5后使用.

* @author qbg

*/

public enum Singleton {

INSTANCE;

public void doSomething(){}

}

四、模式优缺点

优点:

1、对唯一实例的受控访问,由于Singleton类将实例的个数及产生时间都封装了起来,而不是让客户自己生成,所以它严格的控制了客户怎样及何时访问实例。

2、缩小命名空间,单例模式是对全局变量的一种改进,减少了对命名空间的污染。对于java没多大用途,java里没全局变量的概念。

3、允许可变数目的实例,这个需要实现为工厂方法,静态实例的单例模式限制只能生成1个实例。

转载于:/article/1338344.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: