设计模式(一)单例模式:2-懒汉模式(Lazy)

摘要:
设计思想与饿汉模式类似,同样是持有一个自身的引用,只是将new的动作延迟到getinstance()方法中执行。如果在调用getInstance()方法之前进行反射入侵,那么就会打破单例,反之,可以保证单例。˃constructor=LazySingleton1.class.getDeclaredConstructor();constructor.setAccessible;try{LazySingleton1singleton2=constructor.newInstance();Assert.fail();}catch{//Donothing,testpass}}}为什么是synchronized方法?可以使用synchronized代码块+Double-checkLocking+volatile关键字,对LazySingleton进行深一步优化,详情见:第003弹:懒汉型单例模式的演变优势?

思想:

相比于饿汉模式,懒汉模式实际中的应用更多,因为在系统中,“被用到时再初始化”是更佳的解决方案。

设计思想与饿汉模式类似,同样是持有一个自身的引用,只是将 new 的动作延迟到 getinstance() 方法中执行。

public final classLazySingleton {

    private staticLazySingleton instance;

    privateLazySingleton() {
        if (instance != null) {
            throw newIllegalStateException();
        }
    }

    public static synchronizedLazySingleton getInstance() {
        if (instance == null) {
            instance = newLazySingleton();
        }
        returninstance;
    }
}
  • 反射能否打破单例?

对于 LazySingleton,这是个很有趣的问题,虽然我们在私有构造器中增加了 instance==null 的判断,但是由于延迟加载的原因,使得它无法完美地规避反射的入侵。

这涉及到了反射入侵和 getInstance() 方法调用顺序的问题。

如果在调用 getInstance() 方法之前进行反射入侵,那么就会打破单例,反之,可以保证单例。

public classLazySingletonTest {

    @Test
    public void testReflectSuccess() throwsException {
        Constructor<?> constructor = LazySingleton1.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        LazySingleton1 singleton1 =(LazySingleton1) constructor.newInstance();
        LazySingleton1 singleton2 =LazySingleton1.getInstance();
        Assert.assertNotSame(singleton1, singleton2);
    }

    @Test
    public void testReflectFailure() throwsException {
        LazySingleton1 singleton1 =LazySingleton1.getInstance();
        Constructor<?> constructor = LazySingleton1.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        try{
            LazySingleton1 singleton2 =(LazySingleton1) constructor.newInstance();
            Assert.fail();
        } catch(Exception e) {
            //Do nothing, test pass
}
    }
}
  • 为什么是 synchronized 方法?

因为是延迟加载,考虑到多线程情况,需要对方法同步。

  • 同步方法带来的性能问题?

可以使用 synchronized 代码块 + Double-check Locking + volatile 关键字,对 LazySingleton 进行深一步优化,详情见:第003弹:懒汉型单例模式的演变

  • 优势?劣势?

优势:延迟加载。

劣势:不能完全屏蔽反射入侵,而且代码较为繁琐。

免责声明:文章转载自《设计模式(一)单例模式:2-懒汉模式(Lazy)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇initializer_list 列表初始化【NOIP2015提高组Day1】信息传递下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Java 设计模式六原则及23中常用设计模式

一、设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访...

从源码中学习设计模式系列——单例模式序/反序列化以及反射攻击的问题(二)

一、前言 这篇文章是学习单例模式的第二篇,之前的文章一下子就给出来看起来很高大上的实现方法,但是这种模式还是存在漏洞的,具体有什么问题,大家可以停顿一会儿,思考一下。好了,不卖关子了,下面我们来看看每种单例模式存在的问题以及解决办法。 二、每种Singleton 模式的演进 模式一 public classLazySingleton {...

单例模式——java设计模式

单例模式 目录: 一、何为单例 二、使用Java EE实现单例模式 三、使用场景 一、何为单例 确保一个类只有一个实例,并且提供了实例的一个全局访问点 **1.1 单例模式类图 **               1.2 单例模式实现 (1)简单实现 public class MySingleton1 { private static MySingleto...

iOS开发-单例模式

什么是单例模式?>是开发设计模式(共23种)中的1种>它可以保证在程序运行过程,一个类只有一个实例(一个对象),而且该实例易于供外界访问,从而方便地控制了实例个数,并节约系统资源>使用场合:在整个应用程序中,共享一份资源(这份资源只需要创建初始化1次) iOS系统中的一些单例UIApplication(应用程序实例) NSNoti...

设计模式学习-单例模式

1.定义 一个类有且仅有一个实例,并且自行实例化向整个系统提供 2.类图 3.代码示例 网上最多有8中实现方式,其中包括了很多非线程安全的实现。我觉得没有必要。这里提供单例模式的两种实用实现,均为线程安全,这里推荐第一种实现,即实现了线程安全,又实现了懒加载 package com.zhaoyangwoo.singleton; /** * Creat...

23种设计模式之一(单例模式)

单例模式:(确保一个类最多只有一个实例,并提供一个全局访问点)      存在的意义:   有些对象我们只需要一个,如:线程池、缓存、硬件设备等;如果使用多个实例就会造成冲突、不一致等;   比如打印机这个类,如果多个对象同时使用它的输出,打印机类就产生了多个实例,就可能造成打印顺序和内容的混乱; 线程最安全,效率最高的一种写法: 1 public c...