【Java】单例模式(Singleton)
阅读原文时间:2023年07月09日阅读:2

重新搞一波 复习巩固

简单记录 慕课网 Java工程师

文章目录

单例概述

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

什么是单例?

单例,就是整个程序有且仅有一个实例。 该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

设计模式

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,代表了最佳的实践, 通常被有经验的面向对象的软件开发人员所采用。

Christopher Alexander说过:“每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心,这样,你就能一次又一次地使用该方案而不必做重复劳动“。

使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。

设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案, 这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

在项目中合理的运用设计模式可以完美的解决很多问题。

每种模式在现在中都有相应的原理与之对应。

每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案。

面向对象的设计模型很多,但大家认为这23个模式是其他模式的基础。

**创建型模式 (Creational Patterns) **

这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。

  • 工厂模式 (Factory Pattern)

  • 建造者模式 (Builder Pattern)

  • 抽象工厂模式( Abstract Factory Pattern)

  • 原型模式 (Prototype Pattern)

  • 单例模式 (Singleton Pattern)

**结构型模式 (Structural Patterns) **

这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。

  • 适配器模式(Adapter Pattern)
  • 桥接模式(Bridge Pattern)
  • 过滤器模式(Filter、Criteria Pattern)
  • 组合模式(Composite Pattern)
  • 装饰器模式(Decorator Pattern)
  • 外观模式(Facade Pattern)
  • 享元模式(Flyweight Pattern)
  • 代理模式(Proxy Pattern)

**解释器模式 (Behavioral Patterns) **

这些设计模式特别关注对象之间的通信。

  • 责任链模式(Chain of Responsibility Pattern)
  • 命令模式(Command Pattern)
  • 解释器模式(Interpreter Pattern)
  • 迭代器模式(Iterator Pattern)
  • 中介者模式(Mediator Pattern)
  • 备忘录模式(Memento Pattern)
  • 观察者模式(Observer Pattern)
  • 状态模式(State Pattern)
  • 空对象模式(Null Object Pattern)
  • 策略模式(Strategy Pattern)
  • 模板模式(Template Pattern)
  • 访问者模式(Visitor Pattern)

另一类设计模式:J2EE 设计模式。

这些设计模式特别关注表示层。这些模式是由 Sun Java Center 鉴定的。

  • MVC 模式(MVC Pattern)
  • 业务代表模式(Business Delegate Pattern)
  • 组合实体模式(Composite Entity Pattern)
  • 数据访问对象模式(Data Access Object Pattern)
  • 前端控制器模式(Front Controller Pattern)
  • 拦截过滤器模式(Intercepting Filter Pattern)
  • 服务定位器模式(Service Locator Pattern)
  • 传输对象模式(Transfer Object Pattern)

单例模式(Singleton)

滚滚历史,朝代更迭,永恒定律:

  • 一个朝代皇帝只有一个
  • 军队的最高司令官只有一个
  • 一山不容二虎

计算机系统:

  • 驱动程序
  • 打印机后台处理程序(Printer Spooler)
  • 线程池
  • 缓存
  • 日志

目的:

使得类的一个对象成为该类系统中的唯一实例

定义:

一个类有且仅有一个实例,并且自行实例化向整个系统提供

要点:

1、某个类只能有一个实例

2、必须自行创建实例

3、必须自行向整个系统提供这个实例

实现:

1、只提供私有的构造方法

2、含有一个该类的静态私有对象

3、提供一个静态的公有方法用于创建、获取静态私有对象

**主要解决:**一个全局使用的类频繁地创建与销毁。

**何时使用:**当您想控制实例数目,节省系统资源的时候。

**如何解决:**判断系统是否已经有这个单例,如果有则返回,如果没有则创建。

**关键代码:**构造函数是私有的。

单例模式

代码实现方案:

1、饿汉式

2、懒汉式

饿汉式 PK 懒汉式

1、饿汉式在类加载时就创建实例,第一次加载速度快

懒汉式第一次使用时才进行实例化,第一个加载速度慢

饿汉式:空间换时间

懒汉式:时间换空间

2、饿汉式线程安全;懒汉式存在线程风险

解决方案:

1、同步锁

2、双重校验锁

双检锁/双重校验锁(DCL,即 double-checked locking)

**描述:**这种方式采用双锁机制,安全且在多线程情况下能保持高性能。

getInstance() 的性能对应用程序很关键。

实例

public class Singleton {
    private volatile static Singleton singleton;
    private Singleton (){}
    public static Singleton getSingleton() {
    if (singleton == null) {
        synchronized (Singleton.class) {
        if (singleton == null) {
            singleton = new Singleton();
        }
        }
    }
    return singleton;
    }
}

单例模式

优点:

1、在内存中只有一个对象,节省内存空间

2、避免频繁的创建销毁对象,提高性能

3、避免对共享资源的多重占用

缺点:

1、扩展比较困难

2、如果实例化后的对象长期不利用,系统将默认为垃圾进行回收,造成对象状态丢失

没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

单例模式

适合场景:

1、创建对象时占用资源过多,但同时又需要用到该类对象

2、对系统内资源要求统一读写,如读写配置信息

3、当多个实例存在可能引起程序逻辑错误,如号码生成器

SingletonOne.java

package com.imooc.singleton;

//饿汉式:创建对象实例的时候直接初始化  空间换时间
public class SingletonOne {
    //1、创建类中私有构造
    private SingletonOne(){

    }

    //2、创建该类型的私有静态实例
    private static SingletonOne instance=new SingletonOne();

    //3、创建公有静态方法返回静态实例对象
    public static SingletonOne getInstance(){
        return instance;
    }
}

SingletonTwo.java

package com.imooc.singleton;
//懒汉式:类内实例对象创建时并不直接初始化,直到第一次调用get方法时,才完成初始化操作
//时间换空间
public class SingletonTwo {
    //1、创建私有构造方法
    private SingletonTwo(){

    }

    //2、创建静态的该类实例对象
    private static SingletonTwo instance=null;

    //3、创建开放的静态方法提供实例对象
    public static SingletonTwo getInstance(){
        if(instance==null)
            instance=new SingletonTwo();

        return instance;
    }
}

test.java

package com.imooc.test;

import com.imooc.singleton.SingletonOne;
import com.imooc.singleton.SingletonTwo;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        SingletonOne one =SingletonOne.getInstance();
        SingletonOne two=SingletonOne.getInstance();
        System.out.println(one);
        System.out.println(two);
        System.out.println("===================================");
        SingletonTwo one1 =SingletonTwo.getInstance();
        SingletonTwo two1=SingletonTwo.getInstance();
        System.out.println(one1);
        System.out.println(two1);
    }

}

参考资料

[1]-慕课网 Java工程师就业班 - Java 零基础入门-Java面向对象-单例模式

[2]-菜鸟教程 - 单例模式

[3]-设计模式-作者: [[美] Erich Gamma](https://book.douban.com/search/Erich Gamma) / [Richard Helm](https://book.douban.com/search/Richard Helm) / [Ralph Johnson](https://book.douban.com/search/Ralph Johnson) / [John Vlissides](https://book.douban.com/search/John Vlissides)- Design Patterns: Elements of Reusable Object-Oriented Software