单例模式是一种常见的软件设计模式,采用单例设计模式,可以使整个系统中对于某个类,只能存在一个对象实例,并且该类只提供一个取得对象实例的方法。
这种模式的动机在哪?一个系统只能有一个窗口或者文件管理系统;一个系统只能有一个计时工具;如果不使用一定的机制对窗口进行唯一化,将弹出多个窗口,如果这多个窗口的显示的内容一致,则是浪费系统资源;如果不一致,则说明同一个时刻有多个不同的状态,这与实际不符,而用户也不知道相信哪个。所以有时确保系统中某个类的对象只有一个很重要。
那么,这种模式它的优缺点在哪?
优点:
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;说明确实是有且只有同一个实例化对象。