单例模式:
(1)、EN:Ensure a class has only one instance,and provide a global point of access to it.
(2)、CH:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
单例模式的通用类图:
Singleton 类:
package dim.singleton;
public class Singleton {
private static final Singleton singleInstance=new Singleton();
/**
* private constructor
*/
public Singleton() {
// TODO Auto-generated constructor stub
System.out.println("构造函数");
}
public static Singleton GetSingletonIns()
{
return singleInstance;
}
public static void SayHello()
{
System.out.println("Hello I am Singleton !");
}
}
package dim.singleton;
public class TestlSingletonClass {
/**
* @param args
*/
public static void main(String[] args) {
Singleton.GetSingletonIns();
Singleton.SayHello();
}
}
构造函数 Hello I am Singleton !
看结果好像是构造函数只调用一次,Singleton类的代码也和单例模式很像。如果修改测试类代码如下:
package dim.singleton;
public class TestlSingletonClass {
/**
* @param args
*/
public static void main(String[] args) {
Singleton.GetSingletonIns();
new Singleton();//试试new 一个对象
Singleton.SayHello();
}
}
构造函数 构造函数 Hello I am Singleton !由结果可以看出,Singleton 实例化了两次,而且还可以在其他类中new操作。问题出在哪里??
仔细看类图:Singleton 中的构造函数 是 - Singleton() 。而上面的Singleton类中的构造函数是public 【为了印象深刻,上面故意把构造函数设为public】
/**
* 单例模式通用代码
*/
private static final Singleton singleInstance=new Singleton();
/**
* private constructor
*/
private Singleton() {
// TODO Auto-generated constructor stub
System.out.println("构造函数");
}
public static Singleton GetSingletonIns()
{
return singleInstance;
} private Singleton()
{
System.out.println("singleton!");
}
public static Singleton getInstance(String TestStr)
{
synchronized (Singleton.class) {
if(singleton==null)
{
singleton=new Singleton();
}
return singleton;
}
} 如果不加同步代码块。在处理多线程的时候,当系统压力增大的时候,会出现,A线程 判断singleton为null,然后 初始化 Singleton。如果在A还没初始化完成,此时singleton为空,B线程此时判断 singleton为null,可以对singleton 初始化。singleton 被初始化了两次,这样违背了,单例原则确保某一个类只有一个实例。
多线程访问例子:
【1】、方法内部不增加synchrogazed 。
package dim.singleton.lazy;
public class Singleton {
private static Singleton singleton=null;
private String Name="";
private int Num=0;
private Singleton()
{
System.out.println("lazy singleton!");
}
public static Singleton getInstance(String TestStr)
{
System.out.println("Come in="+TestStr);
if(singleton==null)
{
System.out.println("Come in========"+TestStr);
singleton=new Singleton();
}
return singleton;
}
public int getNum() {
return Num;
}
public void setNum(int num) {
Num = num;
}
public void setNameOfsingle(String Name)
{
this.Name=Name;
}
public String getNameOfsingle()
{
return Name;
}
}
package dim.singleton.lazy;
import java.io.IOException;
import java.nio.CharBuffer;
import javax.swing.plaf.SliderUI;
public class TestSingleTonClass {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Runnable testRunA=new Runnable() {
@Override
public void run() {
while(true)
{
// TODO Auto-generated method stub
Singleton.getInstance("A");
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
Thread testThreadA=new Thread(testRunA);
testThreadA.start();
Runnable testRunB=new Runnable() {
@Override
public void run() {
while(true)
{
// TODO Auto-generated method stub
Singleton.getInstance("B");
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
Thread testThreadB=new Thread(testRunB);
testThreadB.start();
}
}
运行多次尝试:
可见:
singleton 被初始化了两次,这样违背了,单例原则确保某一个类只有一个实例。
【2】、方法内部增加synchrogazed
package dim.singleton.lazy;
public class Singleton {
private static Singleton singleton=null;
private String Name="";
private int Num=0;
private Singleton()
{
System.out.println("lazy singleton!");
}
public static Singleton getInstance(String TestStr)
{
synchronized (Singleton.class) {
System.out.println("Come in="+TestStr);
if(singleton==null)
{
System.out.println("Come in========"+TestStr);
singleton=new Singleton();
}
return singleton;
}
}
public int getNum() {
return Num;
}
public void setNum(int num) {
Num = num;
}
public void setNameOfsingle(String Name)
{
this.Name=Name;
}
public String getNameOfsingle()
{
return Name;
}
}
单例模式的构造函数要加private,确保 某一个类只有一个实例。
单例模式使用场景:
(1)、需要定义大量的今天变量和静态方法 。
(2)、项目中,共享访问点或者共享数据。
(3)、创建一个对象需要消耗资源较多时 。
(4)、其他。。
单例模式的缺点:
(1)、 难拓展。
(2)、与单一职责原则有冲突。
(3)、其他。
参考资料:
《设计模式之禅》
相关链接:
有所不足、多多指正、谢谢!
原文地址:http://blog.csdn.net/androidolblog/article/details/45035569