香雨站

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 90|回复: 1

Java常见设计模式之单例设计模式

[复制链接]

4

主题

6

帖子

14

积分

新手上路

Rank: 1

积分
14
发表于 2023-1-16 07:16:00 | 显示全部楼层 |阅读模式
单例设计模式

释义

单例模式,采取一定的方法保证整个上下文中某个类只能存在一个实例对象,并且该类只提供一个取得其对象实例的静态方法。典型的例子是MyBatis中的SqlSessionFactory负责创建SqlSession对象,在MyBatis框架中,SqlSessionFactory是重量级的(需要加载很多配置),它的创建和销毁都比较消耗资源,因此,将它构建为单例可以提升性能。
实现步骤

· 构造器私有。
· 提供静态属性,赋予单例对象。
· 提供静态方法,返回实例对象。
示例代码

需要注意的是单例模式有两种写法,分别是懒汉式和饿汉式,同时需要确保对象是线程安全的,这样才满足单例的要求,以下提供几种实现方式。
饿汉式(静态常量)

public class SingletonTest1 {

    public static void main(String[] args) {
        Singleton1 instance1 = Singleton1.getInstance();
        Singleton1 instance2 = Singleton1.getInstance();

        System.out.printf("相同对象? %s", instance1 == instance2);
    }

}

class Singleton1 {

    private Singleton1() {}

    private static final Singleton1 instance = new Singleton1();

    public static Singleton1 getInstance() {
        return instance;
    }
}
· 优点:无线程安全问题。
· 缺点:类加载时即分配内存空间,提前占用内存。
饿汉式(静态代码块)

public class SingletonTest2 {

    public static void main(String[] args) {
        Singleton2 instance1 = Singleton2.getInstance();
        Singleton2 instance2 = Singleton2.getInstance();

        System.out.printf("相同对象? %s", instance1 == instance2);
    }

}

class Singleton2 {

    private Singleton2() {}

    private static final Singleton2 instance;
   
    static {
        instance = new Singleton2();
    }

    public static Singleton2 getInstance() {
        return instance;
    }
}
饿汉式(枚举)

public class SingletonTest7 {

    public static void main(String[] args) {
        Singleton7 instance1 = Singleton7.getInstance();
        Singleton7 instance2 = Singleton7.getInstance();

        System.out.printf("相同对象? %s", instance1 == instance2);
    }

}

enum Singleton7 {
   
    //默认就是单例对象
    INSTANCE;

    public static Singleton7 getInstance() {
        return INSTANCE;
    }
}

· 枚举默认就是单例的。
懒汉式(静态常量)

public class SingletonTest3 {

    public static void main(String[] args) {
        Singleton3 instance1 = Singleton3.getInstance();
        Singleton3 instance2 = Singleton3.getInstance();

        System.out.printf("相同对象? %s", instance1 == instance2);
    }

}

class Singleton3 {

    private Singleton3() {}

    private static Singleton3 instance;
   
    public static Singleton3 getInstance() {
        
        if (instance == null) {
            instance = new Singleton3();
        }
        return instance;
    }
}
· 缺点:存在线程安全问题。
懒汉式(同步方法)

public class SingletonTest4 {

    public static void main(String[] args) {
        Singleton4 instance1 = Singleton4.getInstance();
        Singleton4 instance2 = Singleton4.getInstance();

        System.out.printf("相同对象? %s", instance1 == instance2);
    }

}

class Singleton4 {

    private Singleton4() {}

    private static Singleton4 instance;

    public static synchronized Singleton4 getInstance() {

        if (instance == null) {
            instance = new Singleton4();
        }
        return instance;
    }
}
· 优点:线程安全。
· 缺点:效率低。
<hr/>懒汉式(双重检查)(推荐)

public class SingletonTest5 {

    public static void main(String[] args) {
        Singleton5 instance1 = Singleton5.getInstance();
        Singleton5 instance2 = Singleton5.getInstance();

        System.out.printf("相同对象? %s", instance1 == instance2);
    }

}

class Singleton5 {

    private Singleton5() {}

    //必须使用volatile关键字,具体含义参见补充说明
    private static volatile Singleton5 instance;

    public static Singleton5 getInstance() {

        if (instance == null) {
            synchronized (Singleton5.class) {
                //马上更新instance的值
                if (instance == null) instance = new Singleton5();
            }
        }
        return instance;
    }
}
· 优点:线程安全,节省内存。
懒汉式(静态内部类)(推荐)

public class SingletonTest6 {

    public static void main(String[] args) {
        Singleton6 instance1 = Singleton6.getInstance();
        Singleton6 instance2 = Singleton6.getInstance();

        System.out.printf("相同对象? %s", instance1 == instance2);
    }

}

class Singleton6 {

    private Singleton6() {}

    //静态内部类特点: 当Singleton6加载时默认不会加载Singleton6Instance
    private static class Singleton6Instance {
        private static final Singleton6 instance = new Singleton6();
        
    }

    public static Singleton6 getInstance() {
        return Singleton6Instance.instance;
    }

}
· 优点:线程安全,节省内存。
<hr/>补充说明

关于volatile关键字,使用volatile修饰成员变量或静态成员变量将使变量具备两层含义,分别是:
· 保证不同线程之间该变量值的可见性,即当某个线程修改了此变量的值后,另一线程立即可见。
· 禁止指令重排序。
什么是指令重排序:
· 当程序运行到volatile变量的读操作或写操作时,在其前面的操作肯定已经全部执行,在其后面的操作肯定还未执行,且该变量值对后面操作立即可见。
· JVM进行指令优化时,不能将在正在访问volatile修饰的变量的语句放在其后面执行,反之也不能把volatile修饰的变量后面的语句放到其前面执行。

欢迎留言交流,欢迎转载,转载请注明出处即可,谢谢大家。。。
回复

使用道具 举报

2

主题

6

帖子

11

积分

新手上路

Rank: 1

积分
11
发表于 5 小时前 | 显示全部楼层
啥玩应呀
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|香雨站

GMT+8, 2025-3-15 20:23 , Processed in 0.116281 second(s), 62 queries .

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.. 技术支持 by 巅峰设计

快速回复 返回顶部 返回列表