设计模式(一)单例模式

单例模式就是只能在类外实例化一个对象

为了保证在类外实例化一个对象,需要做到

1.构造方法私有化,

2.提供一个方法的接口,为了在类外调用这个方法,必须把该方法设置成静态的(如果不设置为静态的,则需要创建对象去调用这个方法,显然私有化构造函数不能创建对象)

单例的优点和缺点:

优点:减少内存创建开销[减少频繁创建和销毁实例的开销]

缺点:没有接口不能实现

单例的实现方式五种:懒汉式,(线程不安全+同步代码块+双重锁机制),饿汉式(普通+创建内部类),枚举

懒汉式代码实现(不线程安全):

最大的问题就是不支持多线程,因为没有加锁synchronized,所以严格意义上它不是单例模式;

分为懒汉单例模式和饿汉单例模式

懒汉单例模式

(-)普通懒汉模式实现

public class Singleton1 {
 private static Singleton1 instance;
 private Singleton1(){}
 public static Singleton1 getInstance()
     {
	    if(instance==null)
	    {
	    instance=new Singleton1();
	    }
        return instance;
    }
}
测试类
public class Demo01 {
    public static void main(String[] args) {
    Singleton1 s1=Singleton1.getInstance();
    Singleton1 s2=Singleton1.getInstance();
    if(s1==s2)
    {
    System.out.println("两个对象是相同的实例");
    }
}

(二)懒汉模式有可能出现多线程并发访问安全性问题(使用同步锁解决)

public class Singleton4 {
     private static Singleton4 instance;
     private Singleton4() {
 }
     /* public static synchronized Singleton4 getInstance()
    {
      if (instance == null) {
      instance = new Singleton4();
    }
      return instance;
    }*/
 public static Singleton4 getInstance()
 {
       synchronized (Thread.class) {
       if (instance == null) {
       instance = new Singleton4();
          }
      }
      return instance;
  }
 }

(三)懒汉模式解决多线程并发访问方法二:双重锁机制

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

饿汉单例模式

(一)普通饿汉单例模式实现

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

(二)饿汉单例模式第二种实现

饿汉模式的缺点是加载的速度慢,因为在加载类的时候就要实例化对象为了解决这个问题,引进了内部类,让其在执行getinstance方法的时候再去加载

public class Singleton6 {
 private Singleton6() {
 }
 private static class Singleton{
   private static Singleton6 instance=new Singleton6();
}
public static Singleton6 getInstance()
 {
  return Singleton.instance;
 }
}

反射破解单例模式

/**

* 使用反射破坏单例模式

*/

public class Demo07 {
   public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException,   InvocationTargetException, InstantiationException {
   Singleton6 s1=Singleton6.getInstance();
//得到构造方法,无论公有还是私有
    Constructor<Singleton6>constructor=Singleton6.class.getDeclaredConstructor();
//对于getDeclaredConstructor方法获得的构造器需要先设置可访问,再实例化对象
    constructor.setAccessible(true);
    Singleton6 s2=constructor.newInstance();
   if(s1!=s2)
   {
    System.out.println("这两个对象不相等");
   }
     else
   {
   System.out.println("这两个对象相等");
}
 
 }
}

枚举破解反射实现单例模式

枚举破解反射的原理 反射在使用newInstance创建对象时,会检查该类是否是枚举修饰,如果是则反射创建失败,报出异常

https://www.cnblogs.com/chiclee/p/9097772.html

public enum  EnumSingleton {

    INSTANCE;

    public EnumSingleton getInstance(){

        return INSTANCE;

    }

}

比较常用的是双重锁机制和枚举

枚举是最佳的实现方法

可以避免反射创建对象,支持序列化(普通的实现单例模式虽然创建的对象相同,但是序列化得到的结果不同)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值