java设计模式之单例模式

单例设计模式所解决的问题就是:保证类的对象在内存中唯一。

举例:

A、B类都想要操作配置文件信息Config.java,所以在方法中都使用了Config con=new Config();但是这是两个不同的对象。对两者的操作互不影响,不符合条件。

解决思路: 

1.不允许其他程序使用new创建该类对象。(别人new不可控) 

2.在该类中创建一个本类实例。 

3.对外提供一个方法让其他程序可以获取该对象。

解决方法:单例模式。

步骤: 

1.私有化该类的构造函数 

2.通过new在本类中创建一个本类对象。 

3.定义一个共有的方法将创建的对象返回。

一、饿汉式

public class Singleton {

private Singleton(){

}

private static final Singleton instance=new Singleton();

public static Singleton getInstance(){

    return instance;

}

为什么方法是静态的:不能new对象却想调用类中方法,方法必然是静态的,静态方法只能调用静态成员,所以对象也是静态的。 

为什么对象的访问修饰符是private,不能是public 吗?不能,如果访问修饰符是Public,则Single.s也可以得到该类对象,这样就造成了不可控。

二、懒汉式

1.静态内部类

public class Singleton2 {

//私有化构造方法,外部无法直接new

private Singleton2(){

}

/**

* 由于内部类不会在类的外部被使用,所以只有在调用getInstance()方法时才会被加载。

* 同时依赖JVM的ClassLoader类加载机制保证了不会出现同步问题。

*

*/

private static class Lazy{

    private static Singleton2 instance=new Singleton2();

}

private static Singleton2 getInstace(){

    return Lazy.instance;

}

2.双重检测锁

public class Singleton3 {

private Singleton3 (){}

private static Singleton3 instance=null;

public static Singleton3 getInstance(){

    if (instance==null) {

        synchronized(Singleton3.class){

            if (instance==null) {

                instance=new Singleton3();

                return instance;

            }

        }

    }

    return instance;

}

}

假设我们现在并没有创建单例对象,即instance==null,那么我们调用getInstance方法的时候,会进入if块,然后进入同步代码块,此时,别的线程如果想要创建Singleton3实例,就必须获取锁;等当前线程创建完实例对象,释放锁之后,假设正巧有几个线程已经进入了if块中,它们会拿到锁,进入同步代码块,但是由于进行了判空操作,所以不会创建Singleton3实例,而是直接返回已经创建好的Singleton3实例。如果有多个其他线程进入了if块,当它们依次进入同步代码块的时候,同理也不会创建新的Singleton3实例。而没有进入if块的线程,判空操作之后不满足条件,进不了if块,而直接执行了下一条语句return instance;其后的线程调用getInstance方法时,只会判断一次instance==null,不满足条件直接返回Singleton3单例instance,这样就大大提高了了执行效率。

单例模式性能总结

优缺点 

饿汉式 线程安全, 调用效率高 不能延迟加载 

懒汉式 线程安全, 可以延迟加载 调用效率不高 

双重检测锁式 线程安全, 调用效率高, 可以延迟加载 

静态内部类式 线程安全, 调用效率高, 可以延迟加载

补充知识

类加载机制 

static关键字的作用是把类的成员变成类相关,而不是实例相关,static块会在类首次被用到的时候进行加载,不是对象创建时,所以static块具有线程安全性

普通初始化块

当Java创建一个对象时, 系统先为对象的所有实例变量分配内存(前提是该类已经被加载过了), 然后开始对这些实例变量进行初始化, 顺序是: 先执行初始化块或声明实例变量时指定的初始值(这两处执行的顺序与他们在源代码中排列顺序相同), 再执行构造器里指定的初始值.

静态初始化块 

又名类初始化块(普通初始化块负责对象初始化, 类初始化块负责对类进行初始化). 静态初始化块是类相关的, 系统将在类初始化阶段静态初始化, 而不是在创建对象时才执行. 因此静态初始化块总是先于普通初始化块执行.

执行顺序 

系统在类初始化以及对象初始化时, 不仅会执行本类的初始化块[static/non-static], 而且还会一直上溯到java.lang.Object类, 先执行Object类中的初始化块[static/non-static], 然后执行其父类的, 最后是自己. 

顶层类(初始化块, 构造器) -> … -> 父类(初始化块, 构造器) -> 本类(初始化块, 构造器)

小结

static{} 静态初始化块会在类加载过程中执行; 

{} 则只是在对象初始化过程中执行, 但先于构造器;

内部类

内部类访问权限

Java 外部类只有两种访问权限:public/default, 而内部类则有四种访问权限:private/default/protected/public. 而且内部类还可以使用static修饰;内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。如果成员内部类Inner用private修饰,则只能在外部类的内部访问,如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。这一点和外部类有一点不一样,外部类只能被public和包访问两种权限修饰。成员内部类可以看做是外部类的一个成员,所以可以像类的成员一样拥有多种权限修饰。

内部类分为成员内部类与局部内部类, 相对来说成员内部类用途更广泛, 局部内部类用的较少(匿名内部类除外), 成员内部类又分为静态(static)内部类与非静态内部类, 这两种成员内部类同样要遵守static与非static的约束(如static内部类不能访问外部类的非静态成员等)

非静态内部类

非静态内部类在外部类内使用时, 与平时使用的普通类没有太大区别;

Java不允许在非static内部类中定义static成员,除非是static final的常量类型

如果外部类成员变量, 内部类成员变量与内部类中的方法里面的局部变量有重名, 则可通过this, 外部类名.this加以区分.

非静态内部类的成员可以访问外部类的private成员, 但反之不成立, 内部类的成员不被外部类所感知. 如果外部类需要访问内部类中的private成员, 必须显示创建内部类实例, 而且内部类的private权限对外部类也是不起作用的:

静态内部类

使用static修饰内部类, 则该内部类隶属于该外部类本身, 而不属于外部类的某个对象.

由于static的作用, 静态内部类不能访问外部类的实例成员, 而反之不然;

匿名内部类

如果(方法)局部变量需要被匿名内部类访问, 那么该局部变量需要使用final修饰.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容

  • 单利模式 定义 保证一个类仅有一个实例,并提供一个访问它的全局访问点。 Singleton:负责创建Singlet...
    PeterHe888阅读 282评论 0 0
  • 之前在开发中老用到一些设计模式可是呢又不是很懂,于是狠下心来琢磨一番。下面是我琢磨后总结的,希望对您有用。如果发现...
    于阗阅读 2,798评论 2 5
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,504评论 18 399
  • Well,not that emotional, but I move the heart. 【说好了不动情,...
    念念不忘的阅读 229评论 1 1
  • 大寒日有感 北京,晴,-9℃。大风蓝色预警。空气质量为良。 大寒更盼寒风烈, 小暖却忧风不还。 霾去...
    刘汉翔阅读 311评论 0 0