码迷,mamicode.com
首页 > 其他好文 > 详细

设计模式之单例模式

时间:2015-05-05 19:38:59      阅读:128      评论:0      收藏:0      [点我收藏+]

标签:设计模式   多线程   单例模式   经验复用   

 1、概念:

       单例模式:

(1)、EN:Ensure a class has only one instance,and provide a global point of access to it.

(2)、CH:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

单例模式的通用类图:

技术分享


2、例子:

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】

技术分享

3、单例模式的类型与通用代码:

(1)饿汉模式:

	/**
	 * 单例模式通用代码 
	 */
	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;
	}


(2)懒汉模式:

	private Singleton()
	{
		System.out.println("singleton!");
	}

	public    static Singleton getInstance(String TestStr)
	{
		synchronized (Singleton.class) {
			if(singleton==null)
				{
					singleton=new Singleton();
				} 
				return singleton;
		}
	
	}	

这里为什么要加synchronized 。不加的话会发生什么情况。

如果不加同步代码块。在处理多线程的时候,当系统压力增大的时候,会出现,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();

	}

}


输出结果:======== 表示通过了 null的判断,可以初始化。

运行多次尝试:

技术分享


技术分享

可见:

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;
	}
}

多次运行发现,singleton 始终被初始化一次。


4、说明:


单例模式的构造函数要加private,确保 某一个类只有一个实例。


单例模式使用场景:

(1)、需要定义大量的今天变量和静态方法 。

(2)、项目中,共享访问点或者共享数据。

(3)、创建一个对象需要消耗资源较多时 。

(4)、其他。。

单例模式的缺点:

(1)、 难拓展。

(2)、与单一职责原则有冲突。

(3)、其他。


 参考资料:

《设计模式之禅》



相关链接:

设计模式六大原则之单一职责原则

设计模式六大原则之里氏替换原则

设计模式六大原则之依赖倒置原则

设计模式六大原则之接口隔离原则

设计模式六大原则之迪米特法则

设计模式六大原则之开闭原则


有所不足、多多指正、谢谢!



设计模式之单例模式

标签:设计模式   多线程   单例模式   经验复用   

原文地址:http://blog.csdn.net/androidolblog/article/details/45035569

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!