转载自http://blog.csdn.net/cjjky/article/details/7318506
【1】基本概念
Singleton 是一种创建性模式,它用来确保只产生一个实例,并提供一个访问它的全局访问点。对一些类来说,保证只有一个实例是很重要的,比如有的时候,数据库连接或 Socket 连接要受到一定的限制,必须保持同一时间只能有一个连接的存在。
【2】简单分析
我们先来看一下该设计模式的UML结构图:
为了实现 Singleton 模式,我们需要的是一个静态的变量,能够在不创建对象的情况下记忆是否已经产生过实例了。静态变量或静态方法都可以在不产生具体实例的情况下直接调用,这样的变量或方法不会因为类的实例化而有所改变。在上面的模式结构图中的 uniqueInstance 就是这个独立的静态变量,它可以记忆对象是否已经实例化了,在静态方法 getInstance() 中对这个变量进行判断,若没有实例化过就产生一个新的对象,如果已经实例化了则不再产生新的对象,仍然返回以前产生的实例。
【3】如何用java语言来实现该设计模式:以下采用2种方法来实现该模式。
第一种方法:用静态方法实现 Singleton 这种方法是使用静态方法来监视实例的创建。为了防止创建一个以上的实例,我们把构造器声明为 private。这样可以防止客户端程序员通过除由我们提供的方法之外的任意方式来创建一个实例。如果不把构造器声明为private,编译器则会创建一个默认的public的构造器。
具体实现的代码如下:
- <SPAN style="FONT-SIZE: 16px">package com.andyidea.patterns.singleton;
- public class Singleton {
- private static Singleton s;
- /**
- * 把构造函数设置为private
- */
- private Singleton(){
- }
- /**
- * 实例化对象的唯一接口
- * @return
- */
- public static Singleton getInstance(){
- if(s == null){
- s = new Singleton();
- }
- return s;
- }
- }</SPAN>
package com.andyidea.patterns.singleton;
public class Singleton {
private static Singleton s;
/**
* 把构造函数设置为private
*/
private Singleton(){
}
/**
* 实例化对象的唯一接口
* @return
*/
public static Singleton getInstance(){
if(s == null){
s = new Singleton();
}
return s;
}
}
测试类代码如下:
- <SPAN style="FONT-SIZE: 16px">package com.andyidea.patterns.client;
- import com.andyidea.patterns.singleton.Singleton;
- /**
- * 设计模式测试类
- * @author Andy.Chen
- *
- */
- public class MainClient {
- public static void main(String[] args) {
- Singleton s1 = Singleton.getInstance();
- Singleton s2 = Singleton.getInstance();
- System.out.println("Welcome to Andy.Chen Blog!" +"\n"
- +"Singleton Patterns." +"\n"
- +"-------------------------------");
- if (s1==s2)
- System.out.println("s1 is the same instance with s2");
- else
- System.out.println("s1 is not the same instance with s2");
- }
- }</SPAN>
package com.andyidea.patterns.client;
import com.andyidea.patterns.singleton.Singleton;
/**
* 设计模式测试类
* @author Andy.Chen
*
*/
public class MainClient {
public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println("Welcome to Andy.Chen Blog!" +"\n"
+"Singleton Patterns." +"\n"
+"-------------------------------");
if (s1==s2)
System.out.println("s1 is the same instance with s2");
else
System.out.println("s1 is not the same instance with s2");
}
}
程序运行的结果如下:
- Welcome to Andy.Chen Blog!
- Singleton Patterns.
- -------------------------------
- s1 is the same instance with s2
Welcome to Andy.Chen Blog!
Singleton Patterns.
-------------------------------
s1 is the same instance with s2
第二种方法:
以静态变量为标志实现 Singleton 在类中嵌入一个静态变量做为标志,每次都在进入构造器的时候进行检查。问题在于构造器没有返回类型,如果确定创建一个实例成功与否.一个方法是调用一个函数来检查创建是否成功,然后简单的返回一个来自静态变量的值,但是这样做是不优雅的,而且容易发生错误。比较好的做法是创建一个当创建了一个以上的实例时可以抛出异常的类,这个类仅仅是调用父类方法,好处是用了自己创建的异常类型,错误信息更加清晰。
具体实现的代码如下:
- <SPAN style="FONT-SIZE: 16px">package com.andyidea.patterns.singleton;
- public class Singleton {
- static boolean instance_flag = false;
- public Singleton() {
- if (instance_flag)
- throw new SingletonException("Only one instance allowed");
- else
- instance_flag = true;
- }
- }</SPAN>
package com.andyidea.patterns.singleton;
public class Singleton {
static boolean instance_flag = false;
public Singleton() {
if (instance_flag)
throw new SingletonException("Only one instance allowed");
else
instance_flag = true;
}
}
异常类代码如下:
- <SPAN style="FONT-SIZE: 16px">package com.andyidea.patterns.singleton;
- /**
- * 异常类
- * @author Andy.Chen
- *
- */
- public class SingletonException extends RuntimeException{
- public SingletonException(String exception){
- super(exception);
- }
- }</SPAN>
package com.andyidea.patterns.singleton;
/**
* 异常类
* @author Andy.Chen
*
*/
public class SingletonException extends RuntimeException{
public SingletonException(String exception){
super(exception);
}
}
测试类代码如下:
- <SPAN style="FONT-SIZE: 16px">package com.andyidea.patterns.client;
- import com.andyidea.patterns.singleton.Singleton;
- import com.andyidea.patterns.singleton.SingletonException;
- /**
- * 设计模式测试类
- * @author Andy.Chen
- *
- */
- public class MainClient {
- public static void main(String[] args) {
- System.out.println("Welcome to Andy.Chen Blog!" +"\n"
- +"Singleton Patterns." +"\n"
- +"-------------------------------");
- Singleton s1, s2;
- // create one incetance--this should always work
- System.out.println("Creating one instance");
- try {
- s1 = new Singleton();
- } catch (SingletonException e) {
- System.out.println(e.getMessage());
- }
- // try to create another incetanced
- System.out.println("Creating two instance");
- try {
- s2 = new Singleton();
- } catch (SingletonException e) {
- System.out.println(e.getMessage());
- }
- }
- }</SPAN>
package com.andyidea.patterns.client;
import com.andyidea.patterns.singleton.Singleton;
import com.andyidea.patterns.singleton.SingletonException;
/**
* 设计模式测试类
* @author Andy.Chen
*
*/
public class MainClient {
public static void main(String[] args) {
System.out.println("Welcome to Andy.Chen Blog!" +"\n"
+"Singleton Patterns." +"\n"
+"-------------------------------");
Singleton s1, s2;
// create one incetance--this should always work
System.out.println("Creating one instance");
try {
s1 = new Singleton();
} catch (SingletonException e) {
System.out.println(e.getMessage());
}
// try to create another incetanced
System.out.println("Creating two instance");
try {
s2 = new Singleton();
} catch (SingletonException e) {
System.out.println(e.getMessage());
}
}
}
运行结果如下:
- Welcome to Andy.Chen Blog!
- Singleton Patterns.
- -------------------------------
- Creating one instance
- Creating two instance
- Only one instance allowed
Welcome to Andy.Chen Blog!
Singleton Patterns.
-------------------------------
Creating one instance
Creating two instance
Only one instance allowed
从输出的结果可以看出,第一个实例可以顺利创建,创建第二个实例的时候抛出了我们自定义的异常信息。