天天看点

java语言实现创建型设计模式—单例模式

一、描述

单例模式就是确保一个类只有一个实例对象,并且在实例对象必须自动创建,对外不提供该对象的构造方法,并向整个系统提供该实例。使用单例模式相当于整个系统共用该类的实例对象,对于java中的并发访问有重要意义。

单例模式又分为饿汉模式和饱汉模式两种,饿汉模式就是在类加载的时候就创建和初始化该类的唯一的实例对象,而饱汉模式是系统需要用到这个类的实例的时候才创建该对象。

二、单例模式的优缺点

优点:在单列模式中,客户端调用类的实例时,只能调用一个公共的接口,这就为整个系统提供了一个共享的对象。因为在系统内存中只存在一个对象,所以可以节约系统资源,相对于那些需要频繁创建和销毁的对象的类来说无疑提高了效率。而且由类自己来控制实例化过程,类就在改变实例化进程上有相应的伸缩性。

缺点:实现单例模式的类在实例化后不能被别的类继承;而且一个类只有唯一的对象,那么这个单例类的职责就会过重,在一定程度上违背了“单一职责原则”;类的实例在初始化后就不能再更改也不适合于类的实例经常变动的场景;如果在分布式系统中,当系统中的单例类被复制到不同的虚拟机下,在每个虚拟机中都会创建一个实例对象,要分清具体哪个虚拟机下运行哪个单例对象比较困难;再者,由于单例模式中的实例是一个共享的概念,在并发访问时需要附加代码保证其访问安全性。

三、源代码

package tong.yue.day4_25;

import java.io.IOException;
/**
 * 单例模式是一种非常常见的设计模式,即一个类只能有一个对象(实例),一般通过将该类的构造器私有化,来阻止在该类外创建该类的对象,并提供给外界一个唯一的对象(这个对象在该类中创建)。
 * java中的单例模式常见的有两种实现方式,一种是恶汉方式,即将该类对象用static休息并且在类加载的时候进行初始化;
 * 另一种是饱汉方式,在程序中需要用到该对象的时候才初始化,一旦初始化一次就不会再重新生成该对象。
 * jdk中的Runtime类其实也是一种单例模式,而且其采用的是饿汉的方式。
 * @author Administrator
 *
 */

public class Singleton {

	public static void main(String[] args) {
		
		//饿汉式获取单例类的对象
		Singleton_eager singleton = Singleton_eager.getInstance();
		singleton.print();
		//饿汉式获取单例类的对象
		Singleton_lazy singleton_lazy = Singleton_lazy.getInstance();
		singleton_lazy.print();		
	}
}
//饿汉式单例模式,在类加载的时候创建一个对象,之后就不再重复创建
class Singleton_eager {
	//声明为static类型,在类加载的时候创建一个对象
	private static Singleton_eager singleton_eager = new Singleton_eager();
	private Singleton_eager(){
		
	}
	
	public static Singleton_eager getInstance() {
		return singleton_eager;
	}
	
	public void print() {
		System.out.println(singleton_eager);
	}
}
//饱汉式单例模式,当程序第一次使用该类的对象时创建对象,只创建一次,之后就不再重复创建
class Singleton_lazy{
	private static Singleton_lazy singleton_lazy = null;
	private Singleton_lazy(){}
	//单例对象的创建方法需要加上同步,因为在多线程并发访问时要保证其访问安全性和统一性。
	public synchronized static Singleton_lazy getInstance() {
		//若是第一次使用该对象,那个就创建一个,否则就使用一个已经创建好的对象
		if (singleton_lazy==null) {
			singleton_lazy = new Singleton_lazy();
		}
		return singleton_lazy;
	}
	
	public void print() {
		System.out.println(singleton_lazy);
	}
}

           

运行结果:

java语言实现创建型设计模式—单例模式

四、总结

以上两种方案的构造函数和公用方法都是静态的(static),则这个类实例是共享的。只是饿汉式在类加载的时候已经创建了对象,每次调用的时候不用再创建而是直接返回已经创建好的实例。这样节省了时间,但却占用了空间,实例本身为static的会一直驻留内存。

懒汉式在类加载时不创建对象,而是在程序使用到这个类的对象时才创建一次,以后每次使用该实例对象,则是判断是否存在,若存在就加载,不存在就创建,这势必会影响程序运行的速度。最关键的是,在并发的情况下,懒汉式是不安全的,如果两个线程:线程1和线程2,在同一时间调用getInstance()方法,如果线程1先进入if语句刚刚判断没有该对象,准备创建对象时,线程发生了切换,然后线程2进行控制判断if语句没有对象也会创建,那么就会有两个实例被创建,所以懒汉式单例模式的getInstance()方法要加上同步控制符synchronized,以保证并发访问的安全性。

继续阅读