java设计模式中的单例模式简单介绍

这篇文章主要介绍“java设计模式中的单例模式简单介绍”,在日常操作中,相信很多人在java设计模式中的单例模式简单介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java设计模式中的单例模式简单介绍”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

莱州网站制作公司哪家好,找创新互联!从网页设计、网站建设、微信开发、APP开发、成都响应式网站建设公司等网站项目制作,到程序开发,运营维护。创新互联2013年至今到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选创新互联

一、引言

单例模式是啥?故名思意,就是单着的意思。没错,就是为了来保证整个系统运行中,从头至尾只有一个对象。比如说,我们最可爱的学校,可以有很多学生,可以有很多主任,但是不能有很多校长。为什么?因为要确保只有一个校长,学校这个系统才不会因为受干扰崩溃,所以单例模式应运而生。

二、实现方式

都知道了单例模式是干嘛的了,那就好办了。首先你要确保整个系统的laowang类只有老王一个对象 最重要的前提你要做什么??可想而知,老王不能被其他类所创造出来啊。

因此有如下做法:

1. 先把构造方法给私有化了(private)。

2. 接着在程序运行的时候创建一个对象放在内存里就得了。

你没看错,要实现单例模式,确确实实就只有这两步,第一步2秒钟搞定,第二步就是我们要来探讨的部分了。

实现单例模式有五种做法:

饿汉式:

也就是在程序装载时提前把对象创建了,有人来就给他。

懒汉式:

在有人需要的时候,再创建第一个对象,然后再给他。(懒加载)

双重检验方式:

内部类方式:

枚举方式:

提示:在上面实现方式中只展现线程安全的做法,详细的我后面会指出。

三、具体实现

1. 饿汉式

分为两步走:

把构造方法私有化

在程序装载时提前创建好实例

class Laowang{

private Laowang(){}//私有化构造方法

private static Laowang laowang=new Laowang();//直接创建静态实例

//对外提供静态方法获取当前的Laowang

public static Laowang getLaowang(){

return laowang;

}

}

//Main方法

public static void main(String[] args) {

//用Laowang类的静态方法getLaowang()获取实例;

Laowang laowang1=Laowang.getLaowang();

Laowang laowang2=Laowang.getLaowang();

//判断laowang1是否和老王2是同一个对象(是输出true,否则false)

System.out.println(laowang1==laowang2);

}

运行结果: true

上面这个例子中,在老王这个类中,先私有化构造方法,接着创建一个静态属性laowang, 然后提供一个对外的静态方法getLaowang()可以给别人拿这个laowang。(因为你已经把构造方法私有化了,所以你只能通过静态方法把laowang给别人。)

Main方法中定义了2个引用laowang1,laowang2,但是都是通过同一种方式拿到实例对象laowang.因此拿到的是同一个对象,所以返回true,这就是饿汉式实现法。

优点:实现简单,线程安全。

缺点:很明显,在类装载的时候直接创建,有时候你不需要它,它也会创 建,造成内存资源浪费。

饿汉式也有另外一种写法,也是一样的效果。把new Laowang()放在静态代码块里,如下:

class Laowang{

private static Laowang laowang;

private Laowang(){}//私有化构造方法

static {

laowang=new Laowang();

}

//对外提供静态方法获取当前的Laowang

public static Laowang getLaowang(){

return laowang;

}

}

2. 懒汉式

在程序需要用到调用的时候才给它(懒加载),因此做法如下:

class Laowang{

private static Laowang laowang;

private Laowang(){}//私有化构造方法

//对外提供静态方法,创建实例然后返回,当前的Laowang

public static synchronized Laowang getLaowang(){

if (laowang == null) {

laowang=new Laowang();

}

return laowang;

}

}

此做法需要在方法声明加上synchronized,(具体作用:比如说很多人来访问这个方法,他们必须排队访问) 这种怎么理解呢?就是说在别人需要用到laowang,调用getLaowang()的时候,先排队,排到他的时候,进去判断laowang是不是为空,是就new一个,不是就拿当前laowang给他。当然main运行结果还是为true这里就不作多的描述。

优点: 不会造成内存浪费

缺点: 很明显,人人平等,大家都要排队,既然排队就慢,高并发情况下,极度影响效率。

在这里解释为什么要加同步锁:如果不加的话,举个例子,程序运行刚开始,小黑和小红同时访问这个方法,同时作判断,肯定同时都判断为空,而且两个人都进去了,new Laowang();很明显直接造成laowang不是单例的了。因此要加锁。 小黑小红都要排队。

3. 双重检验锁

也是属于懒加载

class Laowang{郑州哪个人流医院好 http://www.csyhjlyy.com/

private volatile static Laowang laowang;//必须加上volatile 关键字

private Laowang(){}//私有化构造方法

//对外提供静态方法,创建实例然后返回,当前的Laowang

public static Laowang getLaowang(){

if (laowang == null) {

synchronized (Laowang.class){ //同步代码(照样要排队)

if (laowang==null){

laowang=new Laowang();

}

}

}

return laowang;

}

}

分析一下代码哈,首先静态属性laowang要加上volatile (具体作用要详细了解的话建议百度搜一下哈,属于多线程内容的一部分)。然后再getLaowang()方法中,先判断laowang是否为空,如果为空,请排队。排完队后,再次判断,如果还是为空,才new一个返回。

举个例子解释一下为什么要这样做:

还是小黑小红,同时并发进来访问,然后肯定同时第一次判断都为空,接着两个人排队,小黑先进去玩会,肯定第二次判断为空,结果肯定是小黑new了一个laowang走了。排到小红了,小红进来第二次判断发现laowang不为空了,直接带走。

温馨提示:再看一边再继续看下面内容

这个时候有人问了,那为什么要第一次判断干嘛,直接排队他不香吗?没错,我第一次也这不理解的地方。我们脑回路回退到小黑刚new完laowang走了。刚要排到小红了。突然来了个第三者小三,如果你没有第一次判断,小三还要继续排在小红后面,造成效率降低。但是现在小三第一次判断发现laowang已经不为空了(此时laowang是第一个人小黑弄出来的),直接带走。

优点: 解决了排队效率降低的问题,线程安全。

缺点: 实现较为复杂。

4. 內部类方式

也是属于懒加载,故名思意,首先整个内部类出来,代码如下:

兄台要看如下代码,请先了解final关键字的作用

这里对final作简单描述:

对类使用:表示该类不能被继承(俗称断子绝孙类)

对方法使用:表示该方法不能被重写

对基础类型使用:比如说int,float…表示该值不可以被更改

对引用对象使用:表示该引用从头到尾只指向一个对象

以上3.对基础类型使用,4.对引用对象使用都必须直接赋值。

class Laowang{

private Laowang(){} //私有化构造方法

//对外提供静态方法,调用内部类的属性,返回

public static final Laowang getLaowang(){

return laowangHolder.INSTANCE;

}

//静态内部类

private static final class LaowangHolder{

private static final Laowang INSTANCE =new Laowang();

}

}

解释以上代码:首先声明了一个内部类(LaowangHolder),他有个静态且被final修饰的属性INSTANCE,因此需要直接赋值,new Laowang();接着在getLaowang()方法中调用内部类的INSTANCE属性,返回。因为INSTANCE被final修饰,只指向同一个laowang,所以他是单例的。

5. 枚举方式

这些方法实现相对简单,所以直接上代码:

enum Laowang{

laowang;

public void whateverMethod(){}

}

//Main方法:

public static void main(String[] args) {

//直接当成属性调用就可以了

Laowang laowang1=Laowang.laowang;

Laowang laowang2=Laowang.laowang;

System.out.println(laowang1==laowang2);

}

直接声明一个枚举类,定义一个属性,main方法中直接获取即可。

到此,关于“java设计模式中的单例模式简单介绍”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注创新互联网站,小编会继续努力为大家带来更多实用的文章!


文章题目:java设计模式中的单例模式简单介绍
网页网址:http://azwzsj.com/article/jgeois.html