常用设计模式之单例模式

本文系作者原创,转载请注明:https://www.cnblogs.com/yanfei1819/p/10280671.html

一、要点:

1)某个类只能有一个实例:构造器私有化;

2)必须自行创建这个实例:含有一个该类的静态变量来保存这个唯一的实例;

3)必须自行向整个系统提供这个实例:对外提供获取该实例对象的方式:a.直接暴露;b.用静态变量的get方法获取。

二、有以下几种写法:

  • 饿汉式(静态常量)

    public class Singleton {
        private final static Singleton INSTANCE = new Singleton();
        private Singleton(){}
        public static Singleton getInstance(){
            return INSTANCE;
        }
    }
    
  • 饿汉式(静态代码块)

    public class Singleton {
        private static Singleton instance;
        static {
            instance = new Singleton();
        }
        private Singleton() {}
        public static Singleton getInstance() {
            return instance;
        }
    }
    
  • 懒汉式(线程不安全)

    public class Singleton {
        private static Singleton singleton;
        private Singleton() {}
        public static Singleton getInstance() {
            if (singleton == null) {
                singleton = new Singleton();
            }
            return singleton;
        }
    }
    
  • 懒汉式(线程安全,同步方法)

    public class Singleton {
        private static Singleton singleton;
        private Singleton() {}
        public static synchronized Singleton getInstance() {
            if (singleton == null) {
                singleton = new Singleton();
            }
            return singleton;
        }
    }
    
  • 懒汉式(线程安全,同步代码块)

    public class Singleton {
        private static Singleton singleton;
        private Singleton() {}
        public static Singleton getInstance() {
            if (singleton == null) {
                synchronized (Singleton.class) {
                    singleton = new Singleton();
                }
            }
            return singleton;
        }
    }
    
  • 双重检查

    public class Singleton {
        private static volatile Singleton singleton;
        private Singleton() {}
        public static Singleton getInstance() {
            if (singleton == null) {
                synchronized (Singleton.class) {
                    if (singleton == null) {
                        singleton = new Singleton();
                    }
                }
            }
            return singleton;
        }
    }
    
  • 静态内部类

这种方式既不用加锁,也实现了懒加载。

public class Singleton {
    private Singleton() {}
    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton();
    }
    public static Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }
}
  • 枚举

    public enum Singleton {
        INSTANCE;
        public void whateverMethod() {}
    }
    

三、优点:

1) 减少内存开销,尤其是频繁的创建和销毁实例,提升系统性能;

2)避免对资源对过多占用。

四、缺点:

1)没有抽象层,不利于继承扩展;

2)违背了“单一职责原则”,一个类只重视内部关系,而忽略外部关系;

3)不适用于变化的对象;

4)滥用单例会出现一些负面问题,如为节省资源将数据库连接池对象设计为单例,可能会导致共享连接池对象对程序过多而出现连接池溢出。如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这样将导致对象状态丢失;

5)当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new,可能会给其他开发人员造成困扰,特别是看不到源码的时候。

五、使用场合:

1)需要频繁的进行创建和销毁的对象;

2)创建对象时耗时过多或耗费资源过多,但又经常用到的对象;

3)工具类对象;

4)频繁访问数据库或文件的对象。

原文地址:https://www.cnblogs.com/yanfei1819/p/10280671.html