设计模式一(单例模式)

发布时间:2024年01月22日

主要思路:将构造方法私有化,并对外提供一个static的方法来创建对象

饿汉式单例

public class Hungry {
?
 ? ?private Hungry(){
?
 ?  }
 ? ?private final static Hungry hungry = new Hungry();
 ? ?public static Hungry getInstance(){
 ? ? ? ?return hungry;
 ?  }
?
 ? ?public static void main(String[] args) {
 ? ? ? ?Hungry hungry1 = Hungry.getInstance();
 ? ? ? ?Hungry hungry2 = hungry.getInstance();
 ? ? ? ?System.out.println(hungry1==hungry2);//true
 ?  }
}

缺点:一开始就创建对象,占用系统资源

懒汉式单例

public class Lazy {
?
 ? ?private Lazy(){
 ? ? ? ?System.out.println(Thread.currentThread().getName()+"ok");
 ?  }
?
 ? ?private static Lazy lazy;
?
 ? ?public static Lazy getInstance(){
 ? ? ? ?if(lazy==null){
 ? ? ? ? ? ?lazy = new Lazy();
 ? ? ?  }
 ? ? ? ?return lazy;
 ?  }
?
 ? ?public static void main(String[] args) {
 ? ? ? for(int i=0;i<10;i++){
 ? ? ? ? ? new Thread(()->{
 ? ? ? ? ? ? ? Lazy.getInstance();
 ? ? ? ? ? }).start();
 ? ? ? }
 ?  }
}
?

单线程下不会出现问题,但多线程会会有并发问题,main方法的测试结果:

Thread-0ok
Thread-2ok
Thread-3ok

会发生同一时间创建了多个对象,所以出现了DCL双重检索

DCL懒汉式

public class Lazy {
?
 ? ?private Lazy(){
 ? ? ? ?System.out.println(Thread.currentThread().getName()+"ok");
 ?  }
?
 ? ?private volatile static Lazy lazy; //volatile保证不会出现代码重排
?
 ? ?public static Lazy getInstance(){
 ? ? ? ?if(lazy==null) {
 ? ? ? ? ? ?synchronized (Lazy.class) {
 ? ? ? ? ? ? ? ?if (lazy == null) {
 ? ? ? ? ? ? ? ? ? ?lazy = new Lazy();
 ? ? ? ? ? ? ? ? ? ?/*
 ? ? ? ? ? ? ? ? ? ? ? ?这个过程不是一个原子性,会出现代码重排现象
 ? ? ? ? ? ? ? ? ? ? ? ?1.开配空间
 ? ? ? ? ? ? ? ? ? ? ? ?2.执行构造方法
 ? ? ? ? ? ? ? ? ? ? ? ?3.引用执行
 ? ? ? ? ? ? ? ? ? ? */
 ? ? ? ? ? ? ?  }
 ? ? ? ? ?  }
 ? ? ?  }
 ? ? ? ?return lazy;
 ?  }
?
 ? ?public static void main(String[] args) {
 ? ? ? for(int i=0;i<10;i++){
 ? ? ? ? ? new Thread(()->{
 ? ? ? ? ? ? ? Lazy.getInstance();
 ? ? ? ? ? }).start();
 ? ? ? }
 ?  }
}

可以实现延迟实例化,并且是线程安全的

静态内部类

public class Holder {
 ? ?private Holder(){
 ? ? ? ?System.out.println(Thread.currentThread().getName()+"ok");
 ?  }
?
 ? ?public static Holder getInstance(){
 ? ? ? ?return InnerClass.holder;
 ?  }
?
 ? ?public static class InnerClass{
 ? ? ? ?private static final Holder holder = new Holder();
 ?  }
?
 ? ?public static void main(String[] args) {
 ? ? ? ?for (int i = 0; i < 10; i++) {
 ? ? ? ? ? ?new Thread(()->{
 ? ? ? ? ? ? ? ?Holder.getInstance();
 ? ? ? ? ?  }).start();
 ? ? ?  }
 ?  }
}

反射破解单例模式

可以采用额外的变量进行控制,防止反射

public class Lazy {
?
 ? ?private Lazy(){
 ? ? ? ?synchronized (Lazy.class){
 ? ? ? ? ? ?if(temp == false){
 ? ? ? ? ? ? ? ?temp = true;
 ? ? ? ? ?  }else{
 ? ? ? ? ? ? ? ?throw new RuntimeException("不要用反射破坏单例");
 ? ? ? ? ?  }
 ? ? ?  }
 ?  }
?
 ? ?private volatile static Lazy lazy; //volatile保证不会出现代码重排
?
 ? ?public static Lazy getInstance(){
 ? ? ? ?if(lazy==null) {
 ? ? ? ? ? ?synchronized (Lazy.class) {
 ? ? ? ? ? ? ? ?if (lazy == null) {
 ? ? ? ? ? ? ? ? ? ?lazy = new Lazy();
 ? ? ? ? ? ? ? ? ? ?/*
 ? ? ? ? ? ? ? ? ? ? ? ?这个过程不是一个原子性,会出现代码重排现象
 ? ? ? ? ? ? ? ? ? ? ? ?1.开配空间
 ? ? ? ? ? ? ? ? ? ? ? ?2.执行构造方法
 ? ? ? ? ? ? ? ? ? ? ? ?3.引用指向
 ? ? ? ? ? ? ? ? ? ? */
 ? ? ? ? ? ? ?  }
 ? ? ? ? ?  }
 ? ? ?  }
 ? ? ? ?return lazy;
 ?  }
?
 ? ?public static void main(String[] args) throws Exception {
 ? ? ? ?Lazy lazy = Lazy.getInstance();
 ? ? ? ?Constructor<Lazy> declaredConstructor = Lazy.class.getDeclaredConstructor(null);
 ? ? ? ?declaredConstructor.setAccessible(true);
 ? ? ? ?Lazy lazy1 = declaredConstructor.newInstance();
 ? ? ? ?System.out.println(lazy==lazy1);
 ?  }
}

枚举单例

防止反射破坏

public enum EnumSingleton {
 ? ?INSTANCE;
 ? ?private EnumSingleton() {
?
 ?  }
?
 ? ?public EnumSingleton getInstance(){
 ? ? ? ?return INSTANCE;
 ?  }
?
 ? ?public static void main(String[] args) throws Exception {
 ? ? ? ?EnumSingleton instance = EnumSingleton.INSTANCE;
 ? ? ? ?Constructor<EnumSingleton> declaredConstructor = EnumSingleton.class.getDeclaredConstructor(String.class,int.class);
 ? ? ? ?declaredConstructor.setAccessible(true);
 ? ? ? ?EnumSingleton instance1 = declaredConstructor.newInstance();
 ? ? ? ?System.out.println(instance==instance1);
 ?  }
}

防止反序列化破坏

重写readResolve()方法

private Object readResolve() throws ObjectStreamException{
 ? ? ? ?return singleton;
}
文章来源:https://blog.csdn.net/weixin_64704029/article/details/135756797
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。