随笔 - 82  文章 - 0  评论 - 51  阅读 - 16万

设计模式-单例

上周开发的时候需要做一个校验用户姓名格式的类,因为提供的是公共功能,类似于工具类,所以最好拿来就能用。内部逻辑大体如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class NameValidateUtil {
     
    // 校验姓名格式是否满足要求
    public boolean validateName (String name) {
        // 判断是不是汉字的姓名
        if (isChineseName(name)) {
            // 是汉字,就用汉字的校验逻辑
            return validateChineseName(name);
        } else {
            // 否则是英文,用英文的校验逻辑
            return validateEnglishName(name);
        }
    }
     
    private boolean validateEnglishName(String name) {
        // 此处省略校验逻辑
        return true;
    }
 
    private boolean validateChineseName(String name) {
        // 此处省略校验逻辑
        return true;
    }
 
    private boolean isChineseName(String name) {
        // 此处省略判断逻辑
        return false;
    }
}  

可以看到,校验逻辑比较多,不适合放在一个方法里,如果给每一个方法都加上static也可以做到拿来即用,但这样的设计不够优雅。既然不适合直接用静态的方式,那么很容易就会想到可以用单例模式来实现。其实说实话,在这之前虽然博主也将23中设计模式了解过一遍,但是大多未在项目中实际操作过,所以对设计模式使用的必然性缺少认识,而这一次便让我切身体会到了适合单例模式的使用场景。如上所述的,如果一个类提供的是公共的功能,且不方便给其方法设置成static静态的,那么就可以使用单例模式来实现

对于单例模式,园友们应该都知道老生常谈的那两种:饿汉式和懒汉式。基本的实现方式大家都清楚,此处就不贴了。饿汉式虽然不会出现线程安全的情况,但除非某些特殊场景,一般都不使用。而一般的懒汉式,对于线程安全的解决办法是双重检查锁(dubbo-check),如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class NameValidateUtil {
    // 私有化构造器,让外部无法对该类实例化
    private NameValidateUtil(){}
 
    private static NameValidateUtil nameValidateUtil;
     
    public static NameValidateUtil getSingleton(){
        if (nameValidateUtil == null) {
            synchronized (NameValidateUtil.class) {
                if (nameValidateUtil == null) {
                    nameValidateUtil = new NameValidateUtil();
                }
            }
        }
        return nameValidateUtil;
    }<br>}

但由于JVM的内存模型中允许指令重排序,即在

1
nameValidateUtil = new NameValidateUtil();

这句的三步(a.分配内存地址;b.初始化;c.将内存地址传给引用)中,b与c可能会c先执行,b后执行,这样在高并发的情况下,就可能会出现某个线程获取到了未完成初始化的对象的情况。为避免此情况,可以通过给nameValidateUtil加volatile关键字的方式来避免重排序。

或者使用静态内部类的方式(静态内部类是在使用的时候才会初始化,且JVM能保证只初始化一次),代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class NameValidateUtil {
    // 私有化构造器,让外部无法对该类实例化
    private NameValidateUtil(){}
 
    private static NameValidateUtil nameValidateUtil;
 
    public static NameValidateUtil getSingleton(){
        return InnerNameValidateUtil.innerValidate;
    }
     
    private static class InnerNameValidateUtil {
        static NameValidateUtil innerValidate = new NameValidateUtil();
    }
}

九月份加班成魔,学习进度严重落后,十月份应该就回归正轨了,务必抓紧时间学习!  

 

posted on   淡墨痕  阅读(282)  评论(3编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示