• 设计模式之单例模式(一)


    这篇我们学习的是单例模式,相信很多朋友都或多或少使用过这个模式。很多设计模式的入门,都把单例模式作为第一个的,但是因为我们是跟着书本学习,所以放在了第五个里面。那么,你使用过的单例模式是怎么样的呢?懒汉式?饿汉式?双重校验?静态?

    先来看下定义,单例模式(Singleton Pattern):用来创建独一无二的,只能有一个实例的对象的入场券。而且,单例模式的类图是所有设计模式中最简单的,事实上只有一个类。但是,尽管从类的设计上来说简单,实现上还是会遇见相当多的波折噢。

    单例模式有什么用处?

    有些对象其实我们只需要一个,比方说:线程池、缓存、对话框、处理偏好设置和注册表对象、日志对象等。事实上,这些对象只能以一个实例,如果制造出多个实例,就会导致许多问题的产生,例如:程序的行为异常、资源使用过量,或者就是不一致的结果。

    剖析经典的单例模式实现

    我们先来看下经典的单例模式的实现代码:

    public class Singleton {
    
    	private static Singleton uniqueInstance;
    	
    	private Singleton() {}
    	
    	public static Singleton getInstance() {
    		if (uniqueInstance == null) {
    			uniqueInstance = new Singleton();
    		}
    		return uniqueInstance;
    	}
    }
    
    • 利用一个静态变量来记录Singleton类的唯一实例
    • 把构造器声明为私有化,只有Singleton类才可以调用构造器
    • 用getInstance()方法实例化对象,并返回这个实例

    再仔细看下getInstance()方法,这里需要着重描述下。

    1. uniqueInstance 拥有一个“实例”,而且是一个静态变量
    2. 如果uniqueInstance是空的,表示还没有创建实例
    3. 如果不存在,我们就利用私有的构造器产生一个Singleton实例并把它赋值到uniqueInstance静态变量中。请注意,如果我们不需要这个实例,他就永远不会产生。这就是“延迟实例化”(lazy instaniaze)
    4. 如果uniqueInstance不是null,就表示之前已经创建过对象,我们就直接返回
    5. 当执行到return语句,表示我们已经有实例,并将uniqueInstance当返回值

    如果没有单例模式,这里有一个代码写的很小心的例子,看完你肯定会感受到单例模式的重要性。
    巧克力工厂

    上图中的公司有意识地防止不好的事情发生,对吧。但是,如果防不胜防,同事存在两个ChocolateBoiler实例,可能将发生很糟糕的事情。那么,如果有过个ChocolateBoiler实例存在,可能发生什么严重的事情呢?咋这个例子上,就是会产生资源的浪费,原料的溢出等等。

    那么,你能根据经典的单例模式,写出这个巧克力工厂的单例模式吗?我们晚点揭晓。

    定义单例模式

    单例模式:确保一个类只有一个实例,并提供一个全局访问点。

    这定义一点儿都不让人吃惊,但是让我们更深入一点儿

    • 到底怎么回事?我们正在把某个类设计成自己管理的一个单独实例,同时也避免其他类再自行产生实例。要想取得单例实例,通过单例类是唯一的途径
    • 我们也提供对这个实例的全局访问点:当你需要实例时,向类查询,他会返回单个实例。前面的例子利用延迟实例化的方式创建单例,这种做法对资源敏感的对象特别重要。

    那我们来看看单例的类图:

    你看吧,之前就说过,这个单例模式只有一个类图,是不是很简单呢?仔细看看他吧。

    但是,这些都只是单线程模式下的单例模式,参考上面这个巧克力工厂,如果是多线程模式下的单例,那又会是什么样的呢?经典的单例模式,能确保你在单线程下不出问题,但是,我们想要让人家效率更高,产量更大,势必需要多线程?

    那么,请屏幕前的你,先好好想想,我们下次学习的时候,通过JVM原理,把这个烦恼给解决了。今天的学习就先到这里啦。

    爱生活,爱学习,爱感悟,爱挨踢

  • 相关阅读:
    调用系统相机导致照片旋转问题的修复
    JavaLearning:日期操作类
    PHP实现事件机制实例分析
    按下葫芦起了瓢
    win系统下的eclipse连接和使用linux上的hadoop集群
    利用gradle加入构建版本
    从设计到实现,一步步教你实现Android-Universal-ImageLoader-辅助类
    I帧、P帧和B帧的特点
    tcp_tw_recycle检查tcp_timestamps的内核代码
    OBS源码编译开发
  • 原文地址:https://www.cnblogs.com/dimple91/p/10819163.html
Copyright © 2020-2023  润新知