zoukankan      html  css  js  c++  java
  • Java设计模式——单件模式

    概述

      有一些对象其实我们只需要一个,比方说:线程池(threadpool)、缓存(cache)、对话框、处理偏好设置和注册表(registry)的对象、日志对象,充当打印机、显卡等设备的驱动程序的对象。事实上,这类对象只能有一个实例,如果制造出多个对象,就会导致许多的问题产生,例如:程序的行为异常、资源使用过量,或者是不一致的结果。——《Head First设计模式》


    使用环境

      当我们的对象在逻辑上只能有一个的时候,比如说打印机。想像一下,如果我们有两个指向同一台打印机的对象,这时我们应该去响应哪个对象的请求呢?显然我们只能有一个打印机的对象,且这个对象还要互斥地去访问,否则上述问题依旧存在。


    优点介绍

     1.可以在需要时才开始创建对象

     2.保证只有一对象被创建


    思路分析

    单件模式有两个精髓:

     1.一个私有的构造器

     2.一个静态的成员变量,用于保存类的对象


      如果你没有一个私有的构造器,那么我们完全可以不使用公开的getInstance()方法,而是直接使用类的构造器来实现;如果你没有第一个静态的成员变量来保存对象的对象,你就无法去保证此对象一直存在,这样系统就会在适当的时候回收此对象。


    因为上面两点的约束,我们可以得到一个类似这样的公开化的方法:

    private static SingletonClass mSingletonClass = null;
        
        private SingletonClass() {
        }
        
        public static synchronized SingletonClass getInstance() {
            if (mSingletonClass == null) {
                mSingletonClass = new SingletonClass();
            }
            
            return mSingletonClass;
        }

    上面的代码中使用了关键字synchronized.这是为了在多线程中去互斥地访问临界资源而添加的。

    但是你必须知道,同步一个方法可能造成程序执行效率下降100倍。所以在你的程序中,如果 getInstance() 频繁使用,那么就可能需要重新设计你的代码以提高效率了。


    双重检查加锁

      上面说到 getInstance() 在多线程中的使用可能会有一些不尽如人意的地方。那么要怎么来作一个修改,使得程序更完善呢?利用双重检查加锁可以达到我们的目的。首先检查是否实例已经创建了,如果尚未创建,进行同步。这样的处理,使得程序只会在第一次发生同步,这正是合乎要求的。实现如下:

    public static SingletonDoubleChecked getInstance() {
            if (mDoubleChecked == null) {
                synchronized (SingletonDoubleChecked.class) {
                    if (mDoubleChecked == null) {
                        mDoubleChecked = new SingletonDoubleChecked();
                    }
                }
            }
            
            return mDoubleChecked;
        }

    注意:双重检查加锁不适用于1.4之前的版本。


    类图展示



    代码展示

    SingletonClass.java

    public class SingletonClass {
    
        private static SingletonClass mSingletonClass = null;
        
        private SingletonClass() {
        }
        
        public static synchronized SingletonClass getInstance() {
            if (mSingletonClass == null) {
                mSingletonClass = new SingletonClass();
            }
            
            return mSingletonClass;
        }
        
        public void printLabel() {
            System.out.println("Singleton Class Label.");
        }
    }

    SingletonDoubleChecked.java

    public class SingletonDoubleChecked {
    
        private volatile static SingletonDoubleChecked mDoubleChecked = null;
        
        private SingletonDoubleChecked() {
        }
        
        public static SingletonDoubleChecked getInstance() {
            if (mDoubleChecked == null) {
                synchronized (SingletonDoubleChecked.class) {
                    if (mDoubleChecked == null) {
                        mDoubleChecked = new SingletonDoubleChecked();
                    }
                }
            }
            
            return mDoubleChecked;
        }
        
        public void printLabel() {
            System.out.println("SingletonDoubleChecked Class Label.");
        }
    }

    TestMain.java

    public class TestMain {
    
        public static void main(String[] args) {
            SingletonClass singletonClass = SingletonClass.getInstance();
            singletonClass.printLabel();
            
            SingletonDoubleChecked doubleChecked = SingletonDoubleChecked.getInstance();
            doubleChecked.printLabel();
        }
    }

    效果图



    Github 源码下载

    https://github.com/William-Hai/DesignPatternCollections

  • 相关阅读:
    CSS使用position:sticky 实现粘性布局
    【笔记】原生JS实现验证框架 checkFun
    jQuery与vue分别实现超级简单的绿色拖动验证码功能
    vue从入门到进阶:Vuex状态管理(十)
    vue从入门到进阶:vue-router路由功能(九)
    vue从入门到进阶:渲染函数 & JSX(八)
    vue从入门到进阶:自定义指令directive,插件的封装以及混合mixins(七)
    vue从入门到进阶:组件Component详解(六)
    vue从入门到进阶:过滤器filters(五)
    vue从入门到进阶:Class 与 Style 绑定(四)
  • 原文地址:https://www.cnblogs.com/fengju/p/6336083.html
Copyright © 2011-2022 走看看