单例模式是一种常见的软件设计模式,采用单例设计模式,可以使整个系统中对于某个类,只能存在一个对象实例,并且该类只提供一个取得对象实例的方法。

这种模式的动机在哪?一个系统只能有一个窗口或者文件管理系统;一个系统只能有一个计时工具;如果不使用一定的机制对窗口进行唯一化,将弹出多个窗口,如果这多个窗口的显示的内容一致,则是浪费系统资源;如果不一致,则说明同一个时刻有多个不同的状态,这与实际不符,而用户也不知道相信哪个。所以有时确保系统中某个类的对象只有一个很重要。

那么,这种模式它的优缺点在哪?

优点:

1.因为只有一个实例化对象,所以保证了所有对象访问的都是该类中的同一个对象。

2.因为只有一个实例化对象,节约了内存。

缺点:

1.可能会导致开发混淆:使用单例模式时,开发人员必须记住自己不能new关键字实例化对象。因为无法访问库源代码,开发人员可能会意外发现自己无法直接实例化此类。

2.滥用单例模式会导致一些负面问题:如为了节约资源,将数据库连接池对象设计成单例,可能会导致共享连接池的程序过多导致连接池溢出;如果实例化的对象长时间不用,可能会被系统认为垃圾而回收,导致对象的丢失。

如果我们要使一个类只能有一个对象,首先必须使该类的构造器声明为private,这样,对象实例只能在类内获得,而不能通过new在类的外部获得。其次,因为只能有一个对象,所以要声明成静态的,然后提供一个静态方法在类的外部可以获取该对象。


单例模式分2种:1.饿汉式;


class  Singleton{
	//饿汉式
	
	//私有化构造器
	private Singleton(){
	}
	//在类的内部创建一个类的实例
	private static Singleton singleton=new Singleton();
	//私有化此对象,通过公共的方法来调用
	//创建获取的方法
	public static Singleton GetInstance(){
		return singleton;
	}
	
	
}


   

      2.懒汉式;

class  Singleton2{
	//懒汉式,只有在用到的时候才去创建对象
	private static Singleton2 singleton2=null;
	
	private Singleton2() {
	}
	
	public  static Singleton2 getInstance2(){
		if(singleton2==null){//可能存在线程安全问题;
			singleton2=new Singleton2();
		}
		return singleton2;
	}
	
}



懒汉式可能存在线程安全问题,如果当singleton2==null的时候,一个线程执行完判断语句,未执行下面的new语句,就被暂停了,然后又有一个线程恰好执行到if判断语句,然后new了一个对象,原来的线程恢复后,也会new一个对象,然后就出现了线程安全问题。

改进方法:用synchronized关键字

class  Singleton2{
	//懒汉式,只有在用到的时候才去创建对象
	private static Singleton2 singleton2=null;
	
	private Singleton2() {
	}
	
	public  static Singleton2 getInstance2() throws InterruptedException{
		if(singleton2 == null){//可能存在线程安全问题;
			synchronized (Singleton2.class) {//加锁
			Thread.sleep(100);
				if(singleton2 == null)
			singleton2=new Singleton2();
			}
		}
		return singleton2;
	}
	
}



测试一下:

public class test1 {
	
	public static void main(String[] args) throws InterruptedException {
		//通过调用Singleton的静态方法
		Singleton singleton=Singleton.GetInstance();
		Singleton singleton2=Singleton.GetInstance();
		System.out.println(singleton == singleton2);
		
		
				//通过调用Singleton2的静态方法
			Singleton2  singleton3=Singleton2.getInstance2();
			Singleton2  singleton4=Singleton2.getInstance2();
				System.out.println(singleton3 == singleton4);
	}
	

}


得到的结果是2个true;说明确实是有且只有同一个实例化对象。