博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式之——单例模式
阅读量:6658 次
发布时间:2019-06-25

本文共 3522 字,大约阅读时间需要 11 分钟。

单例模式属于创建模式的一种,在Java中也是最重要、最简单、最常用的设计模式之一,当遇到以下情况时,单例模式就派上用场了。

再比如——对象。。。。。。。。。。。

一般一个类能否做成单例,最容易区别的地方就在于,这些类,在应用中如果有两个或者两个以上的实例会引起错误,又或者我换句话说,就是这些类,在整个应用中,同一时刻,有且只能有一种状态。

单例模式的实现方法主要有四种:饿汉式、懒汉式、工厂方法、枚举方法。前两者是比较常见的的实现方法,当然如果面试时能将后两项也完美阐述的话,说明你的水平可不是一般货色可比的..>.<..下面贴代码,主要阐述都在注释里。。

一、饿汉式

package Singleton;/* * 单例模式 * 应用场合:有些对象只需一个就可以了 * ①要求生成唯一序列号的环境 * ②在整个项目中需要一个共享访问点或共享数据 * ③需要定义大量的静态常量和静态方法(如工具类)的环境,可以使用单例 * ④创建一个对象需要消耗的资源过多,如要访问IO和数据库等资源  *  * 作用:保证整个应用程序中某个实例只有一个,并提供一个访问他的全局访问点 * 类型:饿汉模式,懒汉模式 *  * */public class Singleton {    //饿汉模式:缺点是类实例化后不能添加逻辑        //1.将构造方法私有化,不允许外部直接创建对象    private Singleton(){            }    //2.创建类的唯一实例         static 静态的可将其变为类的成员   private static final Singleton instance=new Singleton();            //3.提供一个用于获取实例的方法    public static Singleton getInstance(){        return instance;    }    }

二、懒汉式

package Singleton;/* * 懒汉模式:只声明实例,并没有实例化 * 但类加载时,并没有创建实例,而当用户获取时,开始做判断(是否为空),若为空,才创建实例 * 创建之后(第2、3、4···)再来获取时,由于实例已存在,就不会再创建实例了 *  * */public class Singleton2 {    //懒汉模式       //1.将构造方法私有化,不允许外部直接创建对象    private Singleton2(){            }    //2.声明类的唯一实例,使用private static 修饰    private static Singleton2 instance;        //3.提供一个用于获取实例的方法,使用public static修饰      public static Singleton2 getInstance(){          if(instance==null){    //多线程下不安全              instance=new Singleton2();          }          return instance;      }        }

三、工厂化方法,可以在创建实例过程中添加逻辑(主要针对懒汉式的缺点)

package Singleton;/** * 工厂化方法:可以在实例过程中添加逻辑 * */public class Singleton3 {    private Singleton3(){            }    private static Singleton3 instance=new Singleton3();        public static Singleton3 getInstance(){        return instance;    }     }

四、枚举类方法(注意是 ~枚举 ~ 类   enum),最佳推荐,代码最简洁  **.**

package Singleton;/** * 枚举类方式:最佳实践,推荐 * effective java 推荐 * */public enum Singleton4 {    instance;}

 

五、对前四种单例方法验证一下,注意看实例创建的方式

package Singleton;/*懒汉模式和饿汉模式的区别: * 懒汉模式:加载类时比较快,但运行时获取对象的速度比较慢,线程不安全 * 饿汉模式:加载类时比较慢,但运行时获取对象的速度比较快(因对象早已创建好),线程安全 *  *  * */public class TestSingleton {    //饿汉模式    public static void main(String[] args) {        System.out.println("饿汉模式");        Singleton s1=Singleton.getInstance();        Singleton s2=Singleton.getInstance();        if(s1==s2){            System.out.println("s1和s2是同一个实例");        }else{            System.out.println("s1和s2是同一个实例");        }                        //懒汉模式        System.out.println("懒汉模式");        Singleton2 s3=Singleton2.getInstance();        Singleton2 s4=Singleton2.getInstance();        if(s3==s4){            System.out.println("s3和s4是同一个实例");        }else{            System.out.println("s3和s4不是同一个实例");        }                        //工厂方法        System.out.println("工厂方法模式");        Singleton3 s5=Singleton3.getInstance();        Singleton3 s6=Singleton3.getInstance();        if(s5==s6){            System.out.println("s5和s6是同一个实例");        }else{            System.out.println("s5和s6不是同一个实例");        }                     //枚举        System.out.println("枚举");        Singleton4 s7=Singleton4.instance;        Singleton4 s8=Singleton4.instance;        if(s7==s8){            System.out.println("s7和s8是同一个实例");        }else{            System.out.println("s7和s8不是同一个实例");        }            }}

运行结果:

 

六、针对最经典的懒汉模式易造成线程不安全的问题再多加一句废话

为什么说懒汉式是最经典的呢?因为饿汉模式这种方式最主要的缺点就是一旦我访问了Singleton的任何其他的静态域,就会造成实例的初始化,而事实是可能我们从始至终就没有使用这个实例,造成内存的浪费。

假设n个线程,当并发访问的时候,第一个调用getInstance方法的线程A,在判断完singleton是null的时候,线程A就进入了if块准备创造实例,但是同时另外一个线程B在线程A还未创造出实例之前,就又进行了singleton是否为null的判断,这时singleton依然为null,所以线程B也会进入if块去创造实例,这时问题就出来了,有两个线程都进入了if块去创造实例,结果就造成单例模式并非单例。

 

转载地址:http://adxto.baihongyu.com/

你可能感兴趣的文章
Quartz---------------->概述
查看>>
idea创建普通java项目以及maven创建项目过程(转)
查看>>
站立会议第五天
查看>>
策略模式
查看>>
maven项目在myeclipse中不出现Maven Dependencies 和maven标识的解决方法
查看>>
py递归
查看>>
配置https服务器系列之一:自制ca证书并配置到nodejs-express服务器
查看>>
poj3625 最小生成树 Prim
查看>>
C# 无法将类型为“__DynamicallyInvokableAttribute”的对象强制转换为类型...
查看>>
C# WinForm 技巧十: winfrom 全屏自适应屏幕分辨率
查看>>
js截取字符串substr和substring的区别
查看>>
响应式调研资料
查看>>
Jenkins 修改主目录正解 workspace
查看>>
set git p4merge tool
查看>>
Using SetAdded and SetModified to Change RowState
查看>>
[Google Guava] 3-缓存
查看>>
php的几种运行模式
查看>>
Python 爬虫:煎蛋网妹子图
查看>>
vim常用命令
查看>>
021、镜像小结(2019-01-14 周一)
查看>>