服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - Java 设计模式以虹猫蓝兔的故事讲解单例模式

Java 设计模式以虹猫蓝兔的故事讲解单例模式

2022-10-26 15:30桃花键神 Java教程

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式

专栏介绍

【JAVA长虹键法】 主要讲了23种设计模式,本系列专栏会以虹猫蓝兔七侠传的故事为例来给大家详细分析所有模式,希望能给大家带来帮助!

本期介绍

模式: 单例模式

案例: 虹猫蓝兔造剑

什么是单例模式

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

注意:

1、单例类只能有一个实例。

2、单例类必须自己创建自己的唯一实例。

3、单例类必须给所有其他对象提供这一实例。

单例模式大致分为懒汉式和饿汉式,接下来用案例分析

懒汉式一

是否 Lazy 初始化: 是

是否多线程安全:否

实现难度: 易

描述: 这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。

这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。

概念看不懂没关系,接下来举例。

案例一:

创建一个剑类,这个类可以实例化一把剑。

虹猫和蓝兔两个人都想要造一把剑,虹猫先打造了一把剑,命名为长虹剑,然后蓝兔也打造了一把剑,但是没有命名。

现在来分析两个情况,一个情况是正常模式,另一种情况是单例模式。

正常模式

剑类:

?
1
2
3
4
5
6
7
8
9
10
11
public class Jians {
    private String name;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}

测试类:

?
1
2
3
4
5
6
7
8
9
10
11
public class Demo1 {
    public static void main(String[] args) {
         //虹猫的剑
        Jians hong = new Jians();
         //蓝兔的剑
        Jians lan = new Jians();
        hong.setName("长虹剑");
        System.out.println(hong.getName());
        System.out.println(lan.getName());
    }
}

结果:

Java 设计模式以虹猫蓝兔的故事讲解单例模式

在正常模式下,我new了虹猫和蓝兔的剑。其实就是两把剑,两个不同的对象。

单例模式

剑类:

剑类中的getInstance()方法有一个造剑的功能,也就是new一个剑对象的功能。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Jian {
    private static Jian jian;
    private String name;
 
    public static Jian getInstance() {
        if (jian == null) {
            jian = new Jian();
        }
        return jian;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}

测试类:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Demo {
    public static void main(String[] args) {
        //虹猫的剑
        Jian hong = Jian.getInstance();
        //蓝兔的剑
        Jian lan = Jian.getInstance();
        //虹猫把剑命名长虹剑
        hong.setName("长虹剑");
        //输出
        System.out.println(hong.getName());
        System.out.println(lan.getName());
    }
}

结果:

Java 设计模式以虹猫蓝兔的故事讲解单例模式

在单例模式下,我new了虹猫和蓝兔的剑。其实就是一把剑,一个相同的对象。

为什么线程不安全呢

单例模式下的剑类:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Jian {
    private static Jian jian;
    private String name;
 
    public static Jian getInstance() {
        if (jian == null) {
            jian = new Jian();
        }
        return jian;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}

就拿这个类来说,他是线程不安全的。因为他通过getInstance()方法来获取对象。如果是多线程运行,有线程1和线程2都先后进入了这个方法,因为线程1刚进入方法还没有返回对象,线程2就进入了方法。所以线程2也会new一个对象,因为此时线程2进入方法的时候jian还是null的。

懒汉式二

是否 Lazy 初始化: 是

是否多线程安全: 是

实现难度: 易

描述: 这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。

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

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

为什么线程安全呢

这里还用上面那个案例,这次主要介绍懒汉式一和懒汉式二的区别。

懒汉式一和懒汉式二的主要区别在剑类上。

懒汉式一的剑类:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Jian {
    private static Jian jian;
    private String name;
 
    public static Jian getInstance() {
        if (jian == null) {
            jian = new Jian();
        }
        return jian;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}

懒汉式二的剑类:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Jian {
    private static Jian jian;
    private String name;
 
    public static synchronized Jian getInstance() {
        if (jian == null) {
            jian = new Jian();
        }
        return jian;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}

在getInstance()方法前加了个字段synchronized,synchronized是一把锁,作用是同一时间只能有一个线程进入这个方法,这样就避免了懒汉式一中两个线程都进入方法的情况出现,就不会new两个对象,所以线程安全。

饿汉式

是否 Lazy 初始化: 否

是否多线程安全: 是

实现难度: 易

描述: 这种方式比较常用,但容易产生垃圾对象。

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

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

饿汉式就是直接在类中new一个对象,就是不管你需不需要剑我已经把剑造好了。

饿汉式剑类:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Jian {
    private static Jian jian=new Jian();
    private String name;
 
    public static synchronized Jian getInstance() {
        return jian;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}

测试类:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Demo {
    public static void main(String[] args) {
        //虹猫的剑
        Jian hong = Jian.getInstance();
        //蓝兔的剑
        Jian lan = Jian.getInstance();
        //虹猫把剑命名长虹剑
        hong.setName("长虹剑");
        //输出
        System.out.println(hong.getName());
        System.out.println(lan.getName());
    }
}

Java 设计模式以虹猫蓝兔的故事讲解单例模式

饿汉式中剑类的getInstance()方法已经失去了造剑的功能,测试类调用它只是返回一把提前造好的剑

懒汉式与饿汉式的区别

还是这个案例,虹猫和蓝兔都想造一把剑,懒汉式是有一个剑类,剑类中有一个造剑的方法,调用这个方法的时候打造一把剑。饿汉式也有一个剑类,不同的是这个剑类直接就把剑造好了,没有造剑的方法,不管你虹猫和蓝兔想不想造剑,剑都已经造好了。

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

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

现在在看饿汉式的优缺点就容易理解了。

下期预告

模式: 简单工厂模式

案例: 虹猫蓝兔莎莉找铸剑师造剑

到此这篇关于Java 设计模式以虹猫蓝兔的故事讲解单例模式的文章就介绍到这了,更多相关Java 单例模式内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://jianshen.blog.csdn.net/article/details/123697600

延伸 · 阅读

精彩推荐
  • Java教程springboot bootcdn使用示例详解

    springboot bootcdn使用示例详解

    这篇文章主要介绍了springboot bootcdn使用,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    o_瓜田李下_o11612021-11-14
  • Java教程MyBatis SELECT基本查询实现方法详解

    MyBatis SELECT基本查询实现方法详解

    这篇文章主要介绍了MyBatis SELECT基本查询实现方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以...

    IT-執念5532020-08-28
  • Java教程深入解析JVM对dll文件和对类的装载过程

    深入解析JVM对dll文件和对类的装载过程

    这篇文章主要介绍了JVM对dll文件的装载和对类的装载过程,针对Java在Windows下的一些运行情况作出讲解,需要的朋友可以参考下 ...

    801976753722020-03-01
  • Java教程Java并发之synchronized实现原理深入理解

    Java并发之synchronized实现原理深入理解

    这篇文章主要介绍了Java中synchronized实现原理详解,涉及synchronized实现同步的基础,Java对象头,Monitor,Mark Word,锁优化,自旋锁等相关内容,具有一定借鉴...

    zejian_6612021-12-08
  • Java教程Java Map的排序实例详解

    Java Map的排序实例详解

    这篇文章主要介绍了 Java Map的排序实例详解的相关资料,希望通过本文大家能够掌握map的排序,需要的朋友可以参考下...

    lxgwm20089872021-01-01
  • Java教程Java Socket实现的传输对象功能示例

    Java Socket实现的传输对象功能示例

    这篇文章主要介绍了Java Socket实现的传输对象功能,结合具体实例形式分析了java socket传输对象的原理及接口、客户端、服务器端相关实现技巧,需要的朋友可...

    kongxx3232020-11-22
  • Java教程Java服务器宕机的解决方法论

    Java服务器宕机的解决方法论

    这篇文章主要介绍了Java服务器宕机的解决方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...

    JavaEdge.6142021-11-05
  • Java教程Linux下Java开发环境搭建以及第一个HelloWorld

    Linux下Java开发环境搭建以及第一个HelloWorld

    这篇文章主要介绍了Linux下Java开发环境搭建以及第一个HelloWorld的实现过程,感兴趣的小伙伴们可以参考一下 ...

    泡面狂5892020-01-04