3.[研磨设计模式笔记]单例模式
2013-06-18 12:44
197 查看
1.定义
保证一个类仅有一个实例,并提供一个访问它的全局访问点。2.解决问题
——读取配置文件的内容不用模式的解决方案public class AppConfig { private String parameterA; private String parameterB; public String getParameterA() { return parameterA; } public String getParameterB() { return parameterB; } public AppConfig() { readConfig(); } private void readConfig() { Properties p = new Properties(); InputStream in = null; try { in = AppConfig.class.getResourceAsStream( “AppConfig.properties”); p.load(in); this.paramterA = p.getProperty(“paramA”); this.paramterB = p.getProperty(“paramB”); } catch(Exception e) { } finally { try { in.close(); } catch(Exception e) { } } } } public class Client { public static void main(String[] args) { AppConfig Config = new AppConfig(); String paramA = config.getParameterA(); String paramB = config.getParameterB(); } }使用单例模式来解决问题(饿汉式)
public class AppConfig { private static AppConfig instance = new AppConfig(); public static AppConfig() getInstance() { return instance; } private String parameterA; private String parameterB; public String getParameterA() { return parameterA; } public String getParameterB() { return parameterB; } private AppConfig() { readConfig(); } private void readConfig() { Properties p = new Properties(); InputStream in = null; try { in = AppConfig.class.getResourceAsStream( “AppConfig.properties”); p.load(in); this.paramterA = p.getProperty(“paramA”); this.paramterB = p.getProperty(“paramB”); } catch(Exception e) { } finally { try { in.close(); } catch(Exception e) { } } } } public class Client { public static void main(String[] args) { AppConfig Config = AppConfig.getInstance(); String paramA = config.getParameterA(); String paramB = config.getParameterB(); } }
3.模式讲解
在不用模式的解决方案中,客户端是通过new一个AppConfig的实例来得到一个操作配置文件内容的对象。如果在系统运行中,有很多地方都需要使用配置文件的内容,也就会有很多地方都创建AppConfig对象的实例。这样系统会同时存在多份配置文件的内容,会严重浪费内存资源。解决思路分析上面的问题,一个类能够/被创建多个实例,问题在于/类的构造方法是公开的,也就是可以/让类的外部/通过构造方法创建多个实例。要控制一个类/只被创建一个实例,那就是把类的构造函数/私有化,然后由这个类来/提供外部访问/类实例的方法,这就是单例模式的实现方式。单例模式使用来保证这个类在运行期间只会被创建一个类实例,另外,单例模式还提供一个全局唯一访问这个类实例的访问点,就是getInstance方法。示例代码(懒汉式)public class Singleton { //4:定义一个变量来存储创建好的类实例 //5:因为这个变量要在静态方法中使用,所以需要加上static修饰 private static Singleton instance = null; //1:私有化构造方法,好在内部控制创建实例的数目 private Singleton() {} //2:定义一个方法来为客户端提供类实例 //3:这个方法需要定义成类方法(静态方法),也就是要加static public static synchronized Singleton getInstance() { //6:判断存储实例的变量是否有值 if(instance == null) { //6.1:如果没有,就创建一个类实例,并把赋值给存储实例的变量 instance = new Singleton(); } //6.2:如果有值,那就直接使用 return instance; } }(饿汉式)
/** * Java中static的特性: * 1.static变量在类加载的时候进行初始化。 * 2.多个实例的static变量会共享同一块内存区域。 * 在Java中static变量只会被初始化一次,就是在类加载的时候,而且多个实例都会共享这个内存空间。 /* public class Singleton { //4:定义一个变量来存储创建好的类实例 //直接在这里创建类实例,只能创建一次 private static Singleton instance = new Singleton(); //1:私有化构造方法,好在内部控制创建实例的数目 private Singleton() {} //2:定义一个方法来为客户端提供类实例 //3:这个方法需要定义成类方法(静态方法),也就是要加static public static Singleton getInstance() { //5:直接使用以创建好的实例 return instance; } }在懒汉式方案里,强制加上static,并没有使用static的特性;而在饿汉式方案里,是主动加上static,使用了static的特性。单例模式的懒汉式实现体现了延迟加载的思想,即就是一开始不要加载资源或数据,一直等,等到要使用这个资源或数据才加载,也成Lazy Load。单例模式的懒汉式实现还体现了缓存的思想,即当某些资源或数据被频繁地使用,而这些资源或数据存储在系统外部(如数据库、硬盘文件等),每次操作这些数据的时候都要去获取。通过把这些数据缓存到内存中,每次操作先到内存里面找,如果有就直接使用,如果没有就去获取,并设置到缓存中,下一次访问的时候就可以直接从内存中获取。应用范围Java里面实现单例的是一个虚拟机范围,虚拟机在通过自己的ClassLoader装载饿汉式实现单例类就会创建一个类的实例。单例模式调用示意图(懒汉式)
(饿汉式)
单例模式的优缺点1.时间和空间懒汉式是典型的时间换空间;饿汉式是典型的空间换时间。2.线程安全不加同步的懒汉式是线程不安全的;饿汉式是线程安全的。双重检查加锁指的是:并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法后,先检查实例是否存在,如果不存在,就在同步的情况下创建一个实例,这是第二重检查。这样,就只需要同步一次,从而减少多次在同步情况下进行判断浪费的时间。双重检查加锁的实现使用了一个关键字volatile,意思是:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存的,从而确保多个线程能正确的处理该变量。
public class Singleton { //对保存实例的变量增加volatile的修饰 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; } }
4.思考
单例模式的本质:控制实例数目何时选用单例模式:如果当:需要控制一个类实例只能有一个,且客户只能从一个全局访问点控制它时,选用单例模式。说明:笔记内容摘自《研磨设计模式》陈臣,王斌关联:整理了一些Java软件工程师的基础知识点
相关文章推荐
- 研磨设计模式之观察者模式 学习笔记
- 2.[研磨设计模式笔记]简单工厂
- 5.[研磨设计模式笔记]装饰模式
- 研磨设计模式学习笔记之单例模式
- 研磨设计模式笔记1
- 研磨设计模式笔记(一)之简单工厂模式
- 4.[研磨设计模式笔记]适配器模式
- PHP设计模式——工厂方法模式(研磨设计模式学习笔记)
- [笔记丶设计模式]3. 简单工厂
- PHP设计模式——适配器模式(研磨设计模式学习笔记)
- 1.[研磨设计模式笔记]设计模式基础
- 6.[研磨设计模式笔记]观察者模式
- 步步为营 .NET 设计模式学习笔记 十五、Composite(组合模式)
- 设计模式之17门面模式(笔记)
- 设计模式学习笔记二:面向对象基础三之多态
- 设计模式:迭代器模式(学习笔记)
- java 设计模式 学习笔记(三)装饰者模式 推荐
- 黑马程序员_学习笔记:3) 面向对象1:概述、封装、this、static、单例设计模式
- js设计模式之迭代器模式学习笔记--封装简单的数组迭代器
- 研磨设计模式之简单工厂模式-3