1 初识单例模式:
定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点
结构:
参考实现:
public class Singleton { //饿汉式 线程安全下 双重检查机制 两个判null 一个synchronized ; //好处在于 线程安全 并 减少多次同步下进行判断所浪费的时间 /** * 对保存实例的变量添加volatile的修饰 这样当一个线程修改后 别的线程能立马感知到 线程之间共享 volatile这个内存空间 并只有在jdk1.5之后才能使用 */ private volatile static Singleton instance = null; private Singleton(){ } public static Singleton getInstance(){ //先检查实例是否存在,如果不存在才进入下面的同步块 if(instance == null){ //同步块,线程安全的创建实例 synchronized(Singleton.class){ //再次检查实例是否存在,如果不存在才真的创建实例 if(instance == null){ instance = new Singleton(); } } } return instance; } }
2 体会单例模式:
场景问题: 读取配置文件的内容(配置文件内容是固定的,在系统中,得到配置文件的实例类仅仅有一个即可)
不用模式的解决方案: 每次都要new对象 并从配置文件中加载, new出多少个对象就加载多少次;
使用模式的解决方案: 将类设计成静态类,那么对象就一个,加载仅仅加载一次配置文件
package cn.javass.dp.singleton.example4; import java.io.*; import java.util.*; /** * 读取应用配置文件,单例实现 */ public class AppConfig { /** * 定义一个变量来存储创建好的类实例,直接在这里创建类实例,只会创建一次 */ private static AppConfig instance = new AppConfig(); /** * 定义一个方法来为客户端提供AppConfig类的实例 * @return 一个AppConfig的实例 */ public static AppConfig getInstance(){ return instance; } /** * 用来存放配置文件中参数A的值 */ private String parameterA; /** * 用来存放配置文件中参数B的值 */ private String parameterB; public String getParameterA() { return parameterA; } public String getParameterB() { return parameterB; } /** * 私有化构造方法 */ private AppConfig(){ //调用读取配置文件的方法 readConfig(); } /** * 读取配置文件,把配置文件中的内容读出来设置到属性上 */ private void readConfig(){ System.out.println("开始咯"); Properties p = new Properties(); InputStream in = AppConfig.class.getResourceAsStream("AppConfig.properties"); try { p.load(in); //把配置文件中的内容读出来设置到属性上 this.parameterA = p.getProperty("paramA"); this.parameterB = p.getProperty("paramB"); } catch (IOException e) { System.out.println("装载配置文件出错了,具体堆栈信息如下:"); e.printStackTrace(); } } } client: public class Client { public static void main(String[] args) { //创建读取应用配置的对象 for(int i=0; i<3; i++){ AppConfig config = AppConfig.getInstance(); String paramA = config.getParameterA(); String paramB = config.getParameterB(); System.out.println("paramA="+paramA+",paramB="+paramB); } } }
3 理解单例模式:
单例模式命名: 建议方法命名为: getInstance()
单例模式:
懒汉式:以时间换取空间(每次都执行if判定,如果有实例,则不new 否则new)
饿汉式:以空间换取时间(直接new出对象来,占用空间)
延迟加载:最开始不加载,直到马上要使用到时才加载。
缓存思想:将经常用到的数据放在内存中,需要用的时候去内存获取(空间换时间)
java中缓存的基本实现:
/** * Java中缓存的基本实现示例 */ public class JavaCache { /** * 缓存数据的容器,定义成Map是方便访问,直接根据Key就可以获取Value了 * key选用String是为了简单,方便演示 */ private Map<String,Object> map = new HashMap<String,Object>(); /** * 从缓存中获取值 * @param key 设置时候的key值 * @return key对应的Value值 */ public Object getValue(String key){ //先从缓存里面取值 Object obj = map.get(key); //判断缓存里面是否有值 if(obj == null){ //如果没有,那么就去获取相应的数据,比如读取数据库或者文件 //这里只是演示,所以直接写个假的值 obj = key+",value"; //把获取的值设置回到缓存里面 map.put(key, obj); } //如果有值了,就直接返回使用 return obj; } }
利用缓存实现单例模式:
public class cacheSingleton { private static cacheSingleton instance; private cacheSingleton(){} public static Map cacheMap = new HashMap(); private static String key = "key1"; public static cacheSingleton getInStance(){ instance = (cacheSingleton) cacheMap.get(key); if(instance == null){ instance = new cacheSingleton(); cacheMap.put(key, instance); } return instance; } }
单例模式优缺点:
懒汉式在多线程下是线程不安全的
但是饿汉式能够保证线程安全,JVM会保证只会装载一次
懒汉式多线程安全,只需在getInstance(){}内new 实例时 增加synchronized即可。
代码写法见文章最开头
java中一种更好的单例实现方式:(Lazy initialization holder class模式)
package cn.javass.dp.singleton.example11; /** * 0 如下写法好处: * 1 实现延迟加载 * 2 实现线程安全 * @author zm * */ public class Singleton { /** * 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例没有绑定关系, * 而且只有被调用到才会装载,从而实现了延迟加载 */ private static class SingletonHolder{ /** * 静态初始化器,由JVM来保证线程安全 */ private static Singleton instance = new Singleton(); } /** * 私有化构造方法 */ private Singleton(){ } public static Singleton getInstance(){ return SingletonHolder.instance; } }
单例和枚举: 单元素的枚举类型已经成为实现Singleton的最佳方法
/** * 使用枚举来实现单例模式的示例 */ public enum Singleton { /** * 定义一个枚举的元素,它就代表了Singleton的一个实例 */ uniqueInstance; /** * 示意方法,单例可以有自己的操作 */ public void singletonOperation(){ //功能处理 } }
4 思考单例模式:
本质: 控制实例数目
何时选用: 大多应用在配置文件获取上吧
5 单例模式 扩展为3个写法:
package cn.javass.dp.singleton.example9; import java.util.*; /** * 简单演示如何扩展单例模式,控制实例数目为3个 * * 1 使用map * 2 使用单例 * 3 设置单例个数,然后将每次生成的对象放在map中 */ public class OneExtend { /** * 定义一个缺省的key值的前缀 */ private final static String DEFAULT_PREKEY = "Cache"; /** * 缓存实例的容器 */ private static Map<String,OneExtend> map = new HashMap<String,OneExtend>(); /** * 用来记录当前正在使用第几个实例,到了控制的最大数目,就返回从1开始 */ private static int num = 1; /** * 定义控制实例的最大数目 */ private final static int NUM_MAX = 3; private OneExtend(){} public static OneExtend getInstance(){ String key = DEFAULT_PREKEY+num; OneExtend oneExtend = map.get(key); if(oneExtend==null){ oneExtend = new OneExtend(); map.put(key, oneExtend); } //把当前实例的序号加1 num++; if(num > NUM_MAX){ //如果实例的序号已经达到最大数目了,那就重复从1开始获取 num = 1; } return oneExtend; } public static void main(String[] args) { OneExtend t1 = getInstance(); OneExtend t2 = getInstance(); OneExtend t3 = getInstance(); OneExtend t4 = getInstance(); OneExtend t5 = getInstance(); OneExtend t6 = getInstance(); System.out.println("t1=="+t1); System.out.println("t2=="+t2); System.out.println("t3=="+t3); System.out.println("t4=="+t4); System.out.println("t5=="+t5); System.out.println("t6=="+t6); } }
6 单例模式脑图:
相关推荐
设计模式——单例 例子和一些ppt 看下没错的
NULL 博文链接:https://794950040.iteye.com/blog/2208104
C++设计模式——单例模式-附件资源
单例的5中实现及反射和反序列化破解单例。
今天给大家带来的是23种设计模式的第一种——单例模式。前天写的第一篇文章设计模式的七大原则,是我第一次写文章,目前看了浏览量,让我信心大增。文章有什么讲述方式不对的欢迎大家随时给我私信。24小时恭候!!...
对应博客讲解:http://blog.csdn.net/t1234xy4/article/details/52419546
单例模式源代码 博文链接:https://yangguangfu.iteye.com/blog/815944
单例模式设计。
1)程序功能:单例模式设计Memcache和Redis操作类,采用PHP编写。 2)程序详解地址:http://blog.csdn.net/clevercode/article/details/46410055。 3)原创作品,出自"CleverCode的博客",分类为《设计模式之PHP项目...
本篇文章主要介绍了android开发设计模式之——单例模式详解,具有一定的参考价值,有需要的可以了解一下。
NULL 博文链接:https://maidoudao.iteye.com/blog/1329564
单例模式的实现饿汉式懒汉式线程安全的懒汉式登记式单例模式的优缺点单例模式的优点单例模式的缺点 单例模式是23个模式中比较简单的模式,应用也非常广泛 什么是单例模式? 单例模式的定义: Ensure a class ...
我们经常遇到这样的场景,线程A和线程B对同一个对象执行操作,但是在A里面new了后,B里面不便取,使的A,B对象是同一个对象,我们就会使用单例模式了。在Android中我们常用于数据库操作,蓝牙命令控制,以及一些工具...
首先我介绍的是设计模式中比较简单的一个模式——单例模式(因为这里只牵涉到一个类) 二、单例模式的介绍 说到单例模式,大家第一反应应该是——什么是单例模式?,从“单例”字面意思上理解为——一个类只有...
最近在设计模式的一些内容,主要的参考书籍是《Head First 设计模式》,同时在学习过程中也查看了很多博客园中关于设计模式的...首先我介绍的是设计模式中比较简单的一个模式——单例模式(因为这里只牵涉到一个类)
单例模式大家并不陌生,也都知道它分为什么懒汉式、饿汉式之类的。但是你对单例模式的理解足够透彻吗?今天我带大家一起来看看我眼中的单例,可能会跟你的认识有所不同。很容易看出,上面这段代码在多线程的情况下是...