java设计模式-----单例

 

单例模式应该是23种设计模式中最简单的一种模式。它包含如下几个要素  java

  1. 1私有的构造方法 
  2. 2指向本身实例的私有静态引用 
  3. 3以本身实例为返回值的静态的公有的方法 


单例模式根据实例化对象的不一样时间分为饿汉和懒汉模式(其中还有一种登记式单例);
饿汉式单例在类被加载时候,实例化一个对象;而懒汉式在调用取得实例方法的时候才会实例化对象 设计模式

单例有以下的优势: 性能

在内存中只有一个对象。 spa

避免频繁的建立销毁对象。 设计

避免对共享资源的多重占用。 code


public class Singleton1
{
	private static Singleton1 instance = new Singleton1();
	
	private Singleton1()
	{
		
	}
	
	public static Singleton1 getInstance()
	{
		return instance;
	}
}

在类第一次加载实例化一个实例,因此在使用时,花销的时间比较少,比较快。 对象


饿汉式单例: 内存

public class Singleton
{
	private static Singleton instance = null;

	private Singleton()
	{
		
	}
	
	public synchronized static Singleton getInstance()
	{
		if(null == instance)
		{
			instance = new Singleton();
		}
		return instance;
	}
}

该单例方式,只有在第一次调用getInstance()时才会初始化一个实例,因此在第一次使用时会花销必定的时间,同时须要同步,一样会花销必定的时间,这样性能上会比第一种要差点,下面咱们会一一的验证。 资源


首先咱们验证一下是否经过单例提供的方法产生的实例是否是就是一个实例? get

Singleton1 instance1 = Singleton1.getInstance();
		instance1.setId("name");
		Singleton1 instance2 = Singleton1.getInstance();
		System.out.println(instance2.getId());


咱们经过getInstance()获取实例,在第一个实例中设置了一个属性值,在获取一个实例,输出他的id的值,

name

咱们并无设置第二个实例属性值,可是他的id值已经被设置为name,这一点说明咱们得到是同一个实例。


这里有一个须要注意的问题,经过反射每次都能得到类的新的实例,因此若是你想使用单例,就不要使用反射建立类的实例对象。

经过下面的例子咱们能够验证一下

Singleton1 instance1 = Singleton1.getInstance();
		instance1.setId("name");
		Singleton1 instance2 = Singleton1.getInstance();
		System.out.println(instance2.getId());
		
		Class c = Class.forName(Singleton1.class.getName());
		Constructor ct = c.getDeclaredConstructor();
		ct.setAccessible(true);
		Singleton1 instance3 = (Singleton1)ct.newInstance();
		System.out.println(instance3.getId());

咱们能够试想下结果应该是什么(上面咱们说明)

name
null

 

上面咱们还提到两种单例的性能问题,下面咱们在用例子说明一下:

//饿汉
		Long startTime1 = System.currentTimeMillis();
		for(int i = 0 ;i<100000000;i++)
		{
			Singleton1 instance = Singleton1.getInstance();
		}
		Long endTime1 = System.currentTimeMillis();
		System.out.println(endTime1 - startTime1);
		
		//懒汉
		Long startTime = System.currentTimeMillis();
		for(int i = 0 ;i<100000000;i++)
		{
			Singleton instance = Singleton.getInstance();
		}
		Long endTime = System.currentTimeMillis();
		System.out.println(endTime - startTime);


经过屡次执行咱们能够看一下结果如何:这里咱们执行了三次

171     187    187 
5398    5398   5429

能够明显的看出饿汉比懒汉式单例性能上好,因此你使用了单例,若是在意性能的话,请使用饿汉式。

相关文章
相关标签/搜索