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

目录
  • 专栏介绍
  • 本期介绍
  • 什么是单例模式
  • 懒汉式一
    • 正常模式
    • 单例模式
    • 为什么线程不安全呢
  • 懒汉式二
    • 为什么线程安全呢
  • 饿汉式
    • 懒汉式与饿汉式的区别

专栏介绍

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

本期介绍

模式: 单例模式

案例: 虹猫蓝兔造剑

什么是单例模式

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

注意:

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

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

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

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

懒汉式一

是否 Lazy 初始化: 是

是否多线程安全:否

实现难度: 易

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

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

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

案例一:

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

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

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

正常模式

剑类:

public class Jians {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

测试类:

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());
    }
}

结果:

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

单例模式

剑类:

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

 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;
    }
}

测试类:

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());
    }
}

结果:

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

为什么线程不安全呢

单例模式下的剑类:

 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 才能保证单例,但加锁会影响效率。

为什么线程安全呢

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

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

懒汉式一的剑类:

 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;
    }
}

懒汉式二的剑类:

 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一个对象,就是不管你需不需要剑我已经把剑造好了。

饿汉式剑类:

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;
    }
}

测试类:

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());
    }
}

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

懒汉式与饿汉式的区别

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

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

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

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

下期预告

模式: 简单工厂模式

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

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

(0)

相关推荐

  • java编程创建型设计模式单例模式的七种示例

    目录 1.什么是单例模式? 2.七种写法 2.1饿汉式(静态常量) 2.2饿汉式(静态代码块) 2.3懒汉式(线程不安全) 2.4懒汉式(线程安全,同步方法) 2.5双重校验锁 2.6静态内部类 2.7枚举 3.单例模式在JDK中的应用(简单的源码分析) 4.单例模式总结 1.什么是单例模式? 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法). 比如Hibernate的 SessionFactory,

  • 深入理解Java设计模式之单例模式

    目录 一.什么是单例模式 二.单例模式的应用场景 三.单例模式的优缺点 四.单例模式的实现 1.饿汉式 2.懒汉式 3.双重加锁机制 4.静态初始化 五.总结 一.什么是单例模式 单例模式是一种常用的软件设计模式,其定义是单例对象的类只能允许一个实例存在. 许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为.比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息.这种方式简

  • Java中常用的设计模式之单例模式详解

    目录 注意 优点 缺点 使用场景 一.实现方式 二.实现方式 三.测试 总结 注意 1.单例类只能有一个实例. 2.单例类必须自己创建自己的唯一实例. 3.单例类必须给所有其他对象提供这一实例. 优点 1.在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存). 2.避免对资源的多重占用(比如写文件操作). 缺点 1.没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化. 使用场景 1.要求生产唯一序列号. 2.WE

  • Java23种设计模式中的单例模式你了解吗

    目录 1.定义 2.适用场景 3.常见写法 4.如何防止单例被破坏 1.多线程破坏单例以及解决方法 2.反射破坏单例以及解决方法 3.序列化破坏单例以及解决方法 5.优缺点 6.总结 1.定义 单例模式(Singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点.隐藏其所有的构造方法.属于创建型模式. 2.适用场景 确保任何情况下都绝对只有一个实例. 3.常见写法 第一种:饿汉式单例:在单例类首次加载时就创建实例 /** * @Package: com

  • Java超详细讲解设计模式之一的单例模式

    目录 单例模式 1.单例模式的结构 2.单例模式的实现 2.1饿汉式 2.2懒汉式 3.单例模式的破坏 3.1序列化和反序列化 3.2反射 单例模式 单例模式顾名思义就是单一的实例,涉及到一个单一的类,该类负责创建自己的对象,同时确保只有一个对象被创建,并且提供一种可以访问这个对象的方式,可以直接访问,不需要实例化该类的对象. 单例模式的特点: 1.单例类只能有一个实例 2.这个实例必须由单例类自己创建 3.单例类需要提供给外界访问这个实例 单例模式的作用: 单例模式主要为了保证在Java应用程

  • Java设计模式之单例模式示例详解

    目录 0.概述 1.饿汉式 1.1 饿汉式单例实现 1.2 破坏单例的几种情况 1.3 预防单例的破坏 2.枚举饿汉式 2.1 枚举单例实现 2.2 破坏单例 3.懒汉式 4.双检锁懒汉式 5.内部类懒汉式 6.JDK中单例的体现 0.概述 为什么要使用单例模式? 在我们的系统中,有一些对象其实我们只需要一个,比如说:线程池.缓存.对话框.注册表.日志对象.充当打印机.显卡等设备驱动程序的对象.事实上,这一类对象只能有一个实例,如果制造出多个实例就可能会导致一些问题的产生,比如:程序的行为异常.

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

    目录 专栏介绍 本期介绍 什么是单例模式 懒汉式一 正常模式 单例模式 为什么线程不安全呢 懒汉式二 为什么线程安全呢 饿汉式 懒汉式与饿汉式的区别 专栏介绍 [JAVA长虹键法] 主要讲了23种设计模式,本系列专栏会以虹猫蓝兔七侠传的故事为例来给大家详细分析所有模式,希望能给大家带来帮助! 本期介绍 模式: 单例模式 案例: 虹猫蓝兔造剑 什么是单例模式 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的

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

    目录 专栏介绍 本期介绍 什么是单例模式 懒汉式一 正常模式 单例模式 为什么线程不安全呢 懒汉式二 为什么线程安全呢 饿汉式 懒汉式与饿汉式的区别 专栏介绍 [JAVA长虹键法] 主要讲了23种设计模式,本系列专栏会以虹猫蓝兔七侠传的故事为例来给大家详细分析所有模式,希望能给大家带来帮助! 本期介绍 模式: 单例模式 案例: 虹猫蓝兔造剑 什么是单例模式 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的

  • Java 设计模式以虹猫蓝兔的故事讲解简单工厂模式

    目录 专栏介绍 本期介绍 什么是简单工厂模式 优点 缺点 应用场景 简单工厂的实现 专栏介绍 本系列专栏会以虹猫蓝兔七侠传的故事为例来给大家详细分析所有模式,希望能给大家带来帮助! 本期介绍 模式: 简单工厂模式 案例: 一个天外陨石(抽象产品),三把剑(产品), 一个铸剑师(工厂). 虹猫蓝兔莎莉分别找铸剑师造了三把剑. 什么是简单工厂模式 工厂模式的定义: 定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中.这满足创建型模式中所要求的"创建与使用相分离"

  • Java 设计模式以虹猫蓝兔的故事讲解建造者模式

    目录 什么是建造者模式 优点 缺点 知识点 建造者模式实现 丹药 抽象丹方 九转仙丹丹方 太虚化神丹丹方 神医豆豆 测试 总结 什么是建造者模式 建造者(Builder)模式的定义: 指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式.它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成.它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的. 优点 1.封装性好,构建和表示分离. 2.扩展性好,各个具体的建造者相

  • Java 设计模式以虹猫蓝兔的故事讲解原型模式

    目录 什么是原型模式 优点 缺点 应用场景 浅克隆 代码实现 总结 深克隆 代码实现 总结 什么是原型模式 原型(Prototype)模式的定义如下: 用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象.在这里,原型实例指定了要创建的对象的种类.用这种方式创建对象非常高效,根本无须知道对象创建的细节.例如,Windows 操作系统的安装通常较耗时,如果复制就快了很多.在生活中复制的例子非常多,这里不一一列举了. 优点 1.Java 自带的原型模式基于内存二进制流的

  • Java设计模式以虹猫蓝兔的故事讲解代理模式

    目录 什么是代理模式 优点 缺点 知识点 代理模式实现 卖酒 干娘的酒馆 大奔的酒摊 测试 总结 模式: 代理模式 案例: 大奔代干娘卖酒 什么是代理模式 代理模式的定义: 由于某些原因需要给某对象提供一个代理以控制对该对象的访问.这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介. 优点 1.代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用: 2.代理对象可以扩展目标对象的功能: 3.代理模式能将客户端与目标对象分离,在一定程度上降低了系统

  • Java设计模式以虹猫蓝兔的故事讲解桥接模式

    目录 什么是桥接模式 优点 缺点 知识点 桥接模式实现 颜色 黄色 红色 裙子 长裙 短裙 测试 总结 模式: 桥接模式 案例: 蓝兔宫主买裙子 什么是桥接模式 桥接(Bridge)模式的定义如下: 将抽象与实现分离,使它们可以独立变化.它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度. 优点 1.抽象与实现分离,扩展能力强 2.符合开闭原则 3.符合合成复用原则 4.其实现细节对客户透明 缺点 由于聚合关系建立在抽象层,要求开发者针对抽象化进行设计与编程,能正确地识

  • Java设计模式以虹猫蓝兔的故事讲解适配器模式

    目录 什么是适配器模式 优点 缺点 知识点 适配器模式实现 类适配器 长虹剑气 火舞旋风剑气 火晶石 测试 对象适配器 长虹剑气 火舞旋风剑气 火晶石 测试 总结 模式: 适配器模式 案例: 虹猫利用火晶石催发火舞旋风剑气 什么是适配器模式 适配器模式(Adapter)的定义如下: 将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作.适配器模式分为类结构型模式和对象结构型模式两种,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的

  • Java设计模式以虹猫蓝兔的故事讲解装饰器模式

    目录 什么是装饰器模式 优点 缺点 知识点 装饰器模式实现 七侠 虹猫 加料 加盐 加孜然 测试 总结 模式: 装饰器模式 案例: 黑小虎抓住了七侠,把虹猫烤了 什么是装饰器模式 装饰器(Decorator)模式的定义: 指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式. 优点 1.装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用 2.通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效

  • Java设计模式之备忘录模式_动力节点Java学院

    定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样就可以将该对象恢复到原先保存的状态 类型:行为类 类图: 我们在编程的时候,经常需要保存对象的中间状态,当需要的时候,可以恢复到这个状态.比如,我们使用Eclipse进行编程时,假如编写失误(例如不小心误删除了几行代码),我们希望返回删除前的状态,便可以使用Ctrl+Z来进行返回.这时我们便可以使用备忘录模式来实现. 备忘录模式的结构 发起人:记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和

随机推荐