当前位置: 首页 >  网技达人 >  单例模式(Singleton Pattern)

单例模式(Singleton Pattern)

导读:单例模式.一、模式动机.单例模式(Singleton Pattern)是结构最简单的设计模式,它的核心结构中只包含一个被称为单例类的特殊类.。通过单例模式可以确保系统中一个类只有一个实例 ,且该实例易于被外界访问,从而方便对实例个数的控制并节约系统资源。.如何确保一个类只有一个实

单例模式

一、模式动机

单例模式(Singleton Pattern)是结构最简单的设计模式,它的核心结构中只包含一个被称为单例类的特殊类 。通过单例模式可以确保系统中一个类只有一个实例 ,且该实例易于被外界访问,从而方便对实例个数的控制并节约系统资源。


  • 如何确保一个类只有一个实例并且这个实例易于被访问?
  1. 定义一个全局变量可以确保对象随时都可以被访问,但是不能防止实例化多个对象。(代码实现)
  2. 更好的办法是让类自身负责创建和保存它的唯一实例,并保证不能创建其他实例,并且提供一个访问该实例的方法。(机制实现)

模式定义

  • 单例模式(Singleton Pattern):确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。
  • 单例模式的要点有三个:
    • 某个类只能有一个实例
    • 必须自行创建这个实例
    • 必须自行向整个系统提供这个实例
  • 单例模式是一种对象创建型模式

三、模式结构

单例类:

public class Singleton {
    //静态私有成员变量
    private static Singleton instance=null;
        //私有构造函数
    private Singleton() {
    }
       //静态公有工厂方法,返回唯一实例
    public static Singleton getInstance() {
        if(instance==null)
            instance=new Singleton();
        return instance;
    }
}

四、案例分析

案例背景

身份证

案例结构

代码实现

单例类

public class IdentityCardNo {

    private static IdentityCardNo instance = null;
    private String no;

    private IdentityCardNo() {
    }

    public static IdentityCardNo getInstance(){

        if (instance == null){
            System.out.println("第一次办理身份证,分配新号码");
            instance = new IdentityCardNo();instance.setNo("No10086111");
        }else
            System.out.println("重复办理身份证,获取旧号码");

        return instance;
    }

    public String getNo() {
        return no;
    }

    public void setNo(String no) {
        this.no = no;
    }
}

测试类

public class Client {

    public static void main(String[] args) {
        IdentityCardNo no1,no2;
        no1 = IdentityCardNo.getInstance();
        no2 = IdentityCardNo.getInstance();
        System.out.println("身份证号码是否一致"+(no1 == no2));

        String str1,str2;
        str1 = no1.getNo();
        str2 = no2.getNo();
        System.out.println("第一次号码:"+str1);
        System.out.println("第二次号码:"+str2);
        System.out.println("内容是否相等:"+str1.equalsIgnoreCase(str2));
        System.out.println("是否是相同对象:"+(str1 == str2));
    }

}

案例结果

五、模式分析

  • 单例模式的实现
  • 私有构造函数
  • 静态私有成员变量(自身类型)
  • 静态公有的工厂方法

  • 单例模式的目的

    • 保证一个类只有一个唯一的实例,并为它提供一个全局访问点。
  • 实现单例模式的思想

    • 为了防止客户端程序使用构造函数来创建多个对象,可以将构造函数声明为私有的,这样客户端程序就不可以使用它来创建任何对象。
  • 单例模式的问题

    • 如果声明构造函数为私有类型,那么没有客户端程序可以使用它来创建任何对象,因此它对客户端程序是无用的。

六、总结

单例模式优点

  • 提供了对唯一实例的受控访问
  • 可以节约系统资源,提高系统的性能
  • 允许可变数目的实例(多例类)

单例模式缺点

  • 扩展困难(缺少抽象层)
  • 单例类的职责过重。单例模式与单一职责原则有冲突。一个类应该只实现一个逻辑,而不关心它是否是单例的,是不是要单例取决于环境,单例模式把“要单例”和业务逻辑融合在一个类中
  • 由于自动垃圾回收机制,可能会导致共享的单例对象的状态丢失

使用情形

  • 系统只需要一个实例对象 ,或者因为资源消耗太大而只允许创建一个对象
  • 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例

扩展

单例模式分类

饿汉式(Eager Singleton):顾名思义,该模式在类被加载时就会实例化一个对象。

public class EagerSingleton {
    private static final EagerSingleton instance = new EagerSingleton(); 
    private EagerSingleton() { }
    public static EagerSingleton getInstance() {
        return instance;
    }
}

懒汉式(Lazy Singlenton):该模式只在你需要对象时才会生成单例对象(比如调用getInstance方法)

public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton() { }

public static LazySingleton getInstance() {
	if (instance == null) {
		instance = new LazySingleton();
    }
	return instance;
}
}

关于Synchronized 类型的方法

  • Synchronized类型的方法限制每个执行此方法的线程必须在执行下一个线程之前完全执行;
  • 通过这种方式,创建的对象在多个线程的情况下是唯一的;
  • 也就是说,我们已经给Synchronized类型的对象添加了锁。当一个线程执行此方法时,其他方法无法接管。其他线程应该等待.
  • 只有在当前线程执行完该方法后,另一个线程才能开始执行该方法

锁方法:

public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton() { }
synchronized public static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
        }
return instance;
}
}

锁代码段

public static LazySingleton getInstance() { 
    if (instance == null) {
        synchronized (LazySingleton.class) {
            instance = new LazySingleton();
        }
    }
    return instance;
}

懒汉式与饿汉式比较

| 懒汉式 | 饿汉式

实例化 外部调用时 类加载时
线程安全 不安全 安全
执行效率 较低 较高
内存 不浪费 浪费

单例模式实现多例

使用单例模式的思想可以实现多例模式,从而确保系统中某个类的对象只能存在有限个

单例类

//单例模式实现多例,实现3个
public class Multiton {

    private static ArrayList<Multiton> array = new ArrayList<>();

    private Multiton() {
    }

    public static Multiton getInstance(){
        if (array.size() < 3){
            System.out.println("创建实例成功");
            Multiton multiton = new Multiton();
            array.add(multiton);
            return multiton;
        }else {
            System.out.println("不再创建更多实例");
            return array.get(new Random().nextInt(array.size()));
        }
    }

    public int random() {
        int rand = (int) (Math.random()*3);
        return rand;
    }


}

客户测试类

public class Client {

    public static void main(String[] args) {
        Multiton m1 = Multiton.getInstance();
        Multiton m2 = Multiton.getInstance();
        Multiton m3 = Multiton.getInstance();
        Multiton m4 = Multiton.getInstance();
        System.out.println("m1=m2"+(m1 == m2));
        System.out.println("m2=m3"+(m2 == m3));
        System.out.println("m3=m4"+(m3 == m4));
    }

}
内容
  • RocketMQ消费者是如何负载均衡的
    RocketMQ消费者是如何负载
    2023-12-09
    摘要:RocketMQ 支持两种消息模式:集群消费( Clustering )和广播消费( Broadcasting )
  • FlashDuty Changelog 2023-09-07 | 新增深色模式与主题配置
    FlashDuty Change
    2023-12-04
    FlashDuty:一站式告警响应平台,前往此地址免费体验!.FlashDuty.现在已经全面支持了深色模式,这为您提供
  • 商务西服
    商务西服
    2023-12-16
    商务西服.商务西服是一款专为商务场合打造的男士正装,其独特的设计和高品质的面料使其成为商务精英们的首选。不论是参加重要的
  • 裤子
    裤子
    2023-12-26
    时尚新品发布:舒适时尚的裤子.产品功能.高品质的面料:采用柔软舒适的面料,透气性好,穿着舒适,不易起皱,易于护理。.人性
  • 领带
    领带
    2023-12-31
    产品介绍:领带.产品功能.提升形象:领带是一种重要的时尚配件,可以为穿着者增加自信并提升整体形象。.衬托服装:领带可以与
  • 儿童运动服
    儿童运动服
    2023-12-16
    儿童运动服.产品功能.我们的儿童运动服采用高品质的面料和工艺制作而成,具有出色的透气性和舒适性,可以让孩子在运动中保持干
  • 外套
    外套
    2023-12-06
    外套.外套是一种经典的服装单品,不仅给人温暖的保护,还可以提升整体的时尚感。我们的外套采用高品质的材料和工艺**而成,既
  • 长裤
    长裤
    2023-12-06
    产品介绍:长裤.产品功能.长裤是一种常见的服装单品,主要用于覆盖双腿,保暖和保护身体。随着时尚的发展,长裤也成为了一种时
  • 儿童衬衫
    儿童衬衫
    2024-01-20
    儿童衬衫.产品功能.舒适的面料,透气性好,适合孩子穿着.简约时尚的设计,适合各种场合穿着.多种颜色和图案选择,满足不同孩
  • 衬衫
    衬衫
    2023-12-31
    产品介绍:衬衫.产品功能.衬衫是一种适合各种场合穿着的服装,既可以正式地穿在工作场所,也可以搭配牛仔裤穿在休闲场合。.衬
  • 袜子
    袜子
    2023-12-26
    产品介绍.产品功能.我们的袜子采用了优质的天然材料,具有吸湿透气、舒适柔软的特点。特别设计的弹性帮助固定袜子位置,并且不
  • 休闲衬衫
    休闲衬衫
    2023-12-21
    休闲衬衫.产品描述.我们的休闲衬衫是男士和女士款式的时尚休闲服装,适合各种休闲场合穿着。我们的衬衫采用优质的面料制成,有