• 设计模式——单例模式


    简介

    单例模式(Singleton Pattern)是Java中最简单的设计模式之一。属于创建型模式。该模式只涉及到一个单一的类,负责创建自己的对象,并且只有单个的对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

    意图

    保证一个类有且只有一个实例,并提供一个访问它的全局访问点。

    主要解决

    一个全局使用的类频繁的创建于销毁

    如何解决

    判断系统是否有这个单利,如果有则返回,如果没有就创建

    关键代码

    构造函数是私有的,然后公开一个GetInstance方法

    图示

    应用实例

    一个党有且只有一个主席

    地球有且只有一个,从有地球这个单例开始,所有的动物都用这个单例而且只有这个单例可用

    登录模块、配置模块

    几种实现方式

    1. 懒汉式

    1.1 懒汉式-线程不安全

    public class Singleton{
        private static Singleton instance;
        //让构造函数为 private,这样该类就不会被实例化
        private Singleton(){}
        public static Singleton getInstance(){
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }

    1.2 懒汉式-线程安全

    public class Singleton{
        private static Singleton instance;
        //让构造函数为 private,这样该类就不会被实例化
        private Singleton(){}
        public static synchronized Singleton getInstance(){
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }

    1.1 最大的问题是不支持多线程,1.2加上锁synchonized就支持了多线程,严格意义上讲1.1不是单例模式。

    优点:第一次调用的时候才初始化,避免内存浪费

    缺点:必须加锁synchonized才能保证单例,但加锁会影响效率

    2. 饿汉式

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

    饿汉式多线程安全,比较常用,但容易产生垃圾对象

    优点:没有加锁,执行效率会提高

    缺点:类加载是就初始化,浪费内存

    它基于 classloder 机制避免了多线程的同步问题,不过,instance 在类装载时就实例化

    3. 双验锁/双重校验锁

    public class Singleton{
        private volatile static Singleton instance;
        private Singleton() {}
        public static Singleton getInstance(){
            if (instance == null){
                instance = new Singleton();
            }
            return instance;
        }
    }

    这种方式安全且在多线程的方式下保持高性能

    实例

    singleton.java

    public class Singleton{
        private volatile static Singleton instance;
        private Singleton() {}
        public static Singleton getInstance(){
            if (instance == null){
                instance = new Singleton();
            }
            return instance;
        }
    }

    SingletonPatternDemo.java

    public class SingletonPatternDemo {
        public static void main(String []args){
            Singleton object = Singleton.getInstance();
            Singleton object2 = Singleton.getInstance();
            System.out.println("End~~~~~~~~~~~");
        }
    }

    推荐1:静态内部类

    public class Singleton1 {
        private static class MySingleton {
            public static final Singleton1 INSTANCE = new Singleton1();
    
        }
        private Singleton1() {
        }
        public static Singleton1 getInstance() {
            return MySingleton.INSTANCE;
        }

    由于静态内部类MySingleton只有在getInstance()方法第一次被调用时,才会被加载,而且构造函数为private,因此该种方式实现了懒汉式的单例模式。不仅如此,根据JVM本身机制,静态内部类的加载已经实现了线程安全。

    推荐2:枚举

    public interface MySingleton {
        void doSomething();
    }
    
    public enum Singleton implements MySingleton {
        INSTANCE {
            @Override
            public void doSomething() {
                System.out.println("complete singleton");
            }
        };
    
        public static MySingleton getInstance() {
            return Singleton.INSTANCE;
        }
    }
    • 枚举类实现其实省略了private类型的构造函数
    • 枚举类的域(field)其实是相应的enum类型的一个实例对象
  • 相关阅读:
    linux中bin和sbin目录的主要区别
    C# 值类型 引用类型 作为参数传递区别
    绿色免安装电视直播软件viviplayer
    [转]中科大校长建议停止以行政主导的高校评估
    MDS 7.0 使用中的问题 2(数据交换中图元的丢失)
    怪异的慢递公司一统快递
    [转]全国最好的医院列表
    多普达D600 问题集锦
    推荐PDG阅读器UnicornViewer
    [转]《乒乓世界》封面故事:中国男乒直板三人行
  • 原文地址:https://www.cnblogs.com/kaituorensheng/p/6507004.html
Copyright © 2020-2023  润新知