单例模式:
(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