Java设计模式—单例模式


仅为记录,仅供参考

单例模式

单例模式的定义

确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一实例。

单例模式的作用

有些类只需要被实例化一次。例如任务管理器窗口,只能有一个状态,如果实例化多个。如果都一样,就是浪费内存,如果不一样,就违反了它的设计要求,同时存在多个状态。

单例模式结构

单例模式类图

  • 定义一个私有的构造函数(如图LoadBalancer),覆盖之前的默认存在的构造函数,私有是为了防止其他类调用。
  • 定义一个私有的静态成员变量(如图instance)私有防止在类外面被修改。静态为了在此类生成的所有对象中共享该变量。假如不用静态变量。生成一个对象,它的静态变量将再次被初始化,也就是例中的null。接下来的公有静态成员方法里面的if语句将永为真。
  • 定义一个公有的静态成员方法,方法里判断私有静态变量是否为null,为null则实例化这个类。(如图getLoadBalancer)

单例模式分类

饿汉式单例类

饿汉式单例类类图

  • 定义一个静态的final变量(如图instance),然后实例化一个这个类放进去,静态,在此类生成的所有对象中共享该变量。final变量,不允许修改
  • 定义一个私有的构造方法(如图EagerSingleton),避免被其他类调用
  • 定义一个公有的静态成员方法(如图getInstance),一调用就返回之前那个变量instance

懒汉式单例类

饿汉式单例类类图

  • 定义一个私有的静态成员变量(如图instance),但没有final,后面还可以修改
  • 定义一个私有的构造方法
  • 定义一个公有的成员方法,在里面实例化这个类放到变量instance,然后返回instance

成员方法里面为了防止多次实例化,还要判断变量instance是否为空。但是仅仅判断一次还不够。
有可能会出现下面这种情况:有可能会有多个线程同时调用
我们应该在成员方法前面加一个synchronized关键字,对方法加锁,保证只有一个线程可执行该方法
这样每次调用该成员方法都要进行线程锁定判断,在多线程高并发访问环境中将会导致系统性能大大降低。所以我们可能会想到,缩小锁的范围
把synchronized关键字放在那个实例化类的语句之前。但是这样会导致几个类都已经执行过if判断语句了,等着执行实例化类的语句。这样会导致if语句失去作用。
所以要把if语句再加一个到里面去。那外面的if语句有什么用呢?如果不满足外面的条件就不需要加锁。线程不需要等待。
由于写了两个if,在Java环境中会被优化,不能给它优化,要加个关键字volatile

懒汉式和饿汉式的区别

  • 懒汉式把实例化对象放在方法里。你要调用方法的时候,它才会给你实例化对象。
  • 而饿汉式对象一上来就实例化对象,放在一个final的静态变量中,需要使用的时候调用他的成员方法就返回这个变量。
  • 懒汉式需要双重锁,在多线程高并发环境中将会导致系统性能大大降低
  • 饿汉式一上来就创建,也需要耗内存

单例模式优缺点

优点

  • 提供了对唯一实例的受控访问
  • 节约系统资源(由于系统内存中只存在一个对象)
  • 允许可变项目的实例,基于单例模式的扩展(例如定义一个私有的静态成员变量,开始设为0,然后每实例化一个对象就+1,然后设个值,超过这个就不能执行实例化的方法)

缺点

  • 没有抽象层
  • 单个类职责过重
  • 很多面向对象语言都提供自动垃圾回收技术,实例化的共享对象长时间不被利用,会被自动销毁并回收资源。下次利用时又将重新实例化,将导致共享的单例对象状态的丢失
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值