设计模式复习--单例模式

简介: 单例模式是一种对象创建型模式,使用单例设计模式可以保证为同一个类只生成唯一的实例对象,也就是说,在整个程序空间中,只存在一个实例对象。   单例模式的定义: 保证一个类,只有一个实例存在,同时提供对该实例加以访问的全局访问方法。

 

单例模式是一种对象创建型模式,使用单例设计模式可以保证为同一个类只生成唯一的实例对象,也就是说,在整个程序空间中,只存在一个实例对象。

 

单例模式的定义:

保证一个类,只有一个实例存在,同时提供对该实例加以访问的全局访问方法。

 

单例模式的需求场景:

1,多线程之间共享同一资源或者操作同一对象。

2,使用全局变量,共享资源。

3,为了性能的考虑,需要节省对象的创建时间。

 

单例模式的实现:

1,俄汉式。

2,懒汉式。

3,双重检查。

单例模式之懒汉模式:

public class Singleton {
        //利用静态变量来记录Singleton的唯一实例
        private static Singleton uniqueInstance;
        
        /*
         * 构造器私有化,只有Singleton类内才可以调用构造器
         */
        private Singleton(){
                
        }
        
        public static Singleton getInstance(){
                if(uniqueInstance == null){
                        uniqueInstance = new Singleton(); } return uniqueInstance; } }

 

如果有两个线程都要执行这段代码,很有可能会产生两个实例对象

第一、  使用synchronized来处理。也就是说将getInstance()方法变成同步方法即可。
public class Singleton {
        //利用静态变量来记录Singleton的唯一实例
        private static Singleton uniqueInstance;
        
        /*
         * 构造器私有化,只有Singleton类内才可以调用构造器
         */
        private Singleton(){
                
        }
        
      //提供全局静态同步方法 public static synchronized Singleton getInstance(){ if(uniqueInstance == null){ uniqueInstance = new Singleton(); } return uniqueInstance; } }

 第二,单例模式之饿汉式模式--直接初始化静态变量。这样就保证了线程安全:

public class Singleton {
        /*
         * 利用静态变量来记录Singleton的唯一实例
         * 直接初始化静态变量,这样就可以确保线程安全了
         */
        private static Singleton uniqueInstance = new Singleton();
        
        /*
         * 构造器私有化,只有Singleton类内才可以调用构造器
         */
        private Singleton(){
                
        }
        
        public static Singleton getInstance(){
                return uniqueInstance;
        }
}

 第三、  用“双重检查加锁”,在getInstance()中减少使用同步。

public class Singleton {
        /*
         * 利用静态变量来记录Singleton的唯一实例
         * volatile 关键字确保:当uniqueInstance变量被初始化成Singleton实例时,
         * 多个线程正确地处理uniqueInstance变量
         * 
         */
        private volatile static Singleton uniqueInstance;
        
        /*
         * 构造器私有化,只有Singleton类内才可以调用构造器
         */
        private Singleton(){
                
        }
        
        /*
         * 
         * 检查实例,如果不存在,就进入同步区域
         */
        public static Singleton getInstance(){
                if(uniqueInstance == null){
                        synchronized(Singleton.class){    //进入同步区域
                                if(uniqueInstance == null){     //在检查一次,如果为null,则创建
                                        uniqueInstance  = new Singleton(); } } } return uniqueInstance; } }

在这里是首先检查是否实例已经创建了,如果尚未创建,才会进行同步。这样一来。只有第一次会同步。

 单例设计模式的优点和缺点:

优点:

1,减少对象创建,节省系统资源,提高系统性能。

缺点:

1,不利于扩展。

在android开发中使用的场景:

源码里面:详见:http://www.cnblogs.com/yemeishu/archive/2013/01/04/2843705.html

说下App场景下单利常用的场景:

如下是我以前项目里面使用ormlite数据时做的一个数据库管理的类,通过DBManager.getInstance(context)获取到单利的dbmanager对象,从而进一步获取数据库操作层的dao对象,以及全局清理数据库里面内容的操作:

/**
 * 数据库管理类 
 */
public class DBManager {
    private OrmLiteSqliteOpenHelper helper;
    private static DBManager instance;

    private DBManager(Context context) {
        helper = OpenHelperManager.getHelper(context, DBHelper.class);
    }

    /**
     * 获取该类实例
     * 
     * @param context
     *            上下文
     * @return
     */
    public synchronized static DBManager getInstance(Context context) {
        if (instance == null) {
            instance = new DBManager(context);
        }
        return instance;
    }

    /**
     * 获取对应数据表的dao
     * 
     * @param clazz
     *            表对应的Bean
     * @return
     */
    public <T, ID> Dao<T, ID> getDao(Class<T> clazz) {
        try {
            return helper.getDao(clazz);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 清除过期的数据
     * 
     * @param tableName
     *            表名
     * @param value
     *            移动天数(0当天,-1向前一天)
     */
    public void clear(String tableName, int value) {
        SQLiteDatabase db = helper.getWritableDatabase();
        try {
            long date = DateUtil.getTimeInMillis(value);
            String[] args = { String.valueOf(date) };
            db.delete(tableName, "updateTime" + "<?", args);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // db.close();
        }
    }

    /**
     * 清除给定表中的所有数据
     */
    public void clearAll(String tableName) {
        SQLiteDatabase db = helper.getWritableDatabase();
        db.delete(tableName, null, null);
    }

    public OrmLiteSqliteOpenHelper getHelper() {
        return helper;
    }

    /**
     * 清除7天前的数据
     * 
     * @param tableName
     */
    public void clear(String tableName) {
        clear(tableName, -7);
    }

    /**
     * 释放资源
     */
    public void release() {
        OpenHelperManager.releaseHelper();
    }

}

 


 

2015年11月30日23:30:56更新

最近在读Mr.simple的设计模式的书,书中讲到了除了以上的集中方式以外的实现单利模式的几种实现:

1,静态内部类单利模式(比较推荐的实现模式)

  Java中静态内部类可以访问其外部类的成员属性和方法,同时,静态内部类只有当被调用的时候才开始首次被加载,保证线程安全,保证单利对象的唯一性,延迟单利实例化。

public class Singleton
{
    private Singleton(){ }

    public static Singleton getInstance()
    {
        return Singletonholder.instance;        
    }

    //在第一次被引用时被加载
    static class Singletonholder
    {
        private static Singleton instance = new Singleton();
    }

    public static void main(String args[])
    {
        Singleton instance = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();
        System.out.println(instance == instance2);
    }
}

结果为:true

2,通过枚举的方式来实现单利

不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。但是失去了类的一些特性,没有延迟加载,枚举是线程安全的

public enum Singleton{
    INSTANCE;

    String getMessage(){
        return "you are doubi";
    }

    public static void main(String[] args) {
        String message = Singleton.INSTANCE.getMessage();
        System.out.println(message);
    }
}

输出结果:

you are doubi

通过枚举实现的相关讨论:http://segmentfault.com/q/1010000000646806

3,使用容器实现单利模式

 一般是通过一个专门的类对各单例模式的此单一实例进行管理和维护。通过Map方式可以方便的实现此中目的

首先复习下map相关知识点:

一个映射不能包含重复的键,每个键最多只能映射到一个值

Map的键唯一,因此如下className是唯一的,如果map中不存在,就实例化对象,并放入map集合(这个原理好骚,哈哈哈)

public class MySingleTonManager {

    private static Map singleTonMap = new HashMap();

    public static void main(String[] args) {
        // 获取A类的单例
        A a = (A) getInstance(A.class.getName());
        // 获取B类的单例
        B b = (B) getInstance(B.class.getName());
    }

    // 根据类型获取单例
    public static Object getInstance(String className) {
        // 判断singleTonMap中是否有此单例,有则取得后返回,无则添加单例后返回
        if (!singleTonMap.containsKey(className)) {
            try {
                singleTonMap.put(className, Class.forName(className).newInstance());
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return singleTonMap.get(className);
    }
}

class A {

}

class B {

}

 注意点:

传递给单利对象的context对象最好是Application Context。

 

 

相关文章
|
设计模式 缓存 安全
【设计模式】【创建型模式】单例模式(Singleton)
一、入门 什么是单例模式? 单例模式是一种设计模式,确保一个类只有一个实例,并提供一个全局访问点。它常用于需要全局唯一对象的场景,如配置管理、连接池等。 为什么要单例模式? 节省资源 场景:某些对象创
448 15
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
165 2
|
设计模式 安全 Java
设计模式:单例模式
单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供全局访问点。它通过私有化构造函数、自行创建实例和静态方法(如`getInstance()`)实现。适用于数据库连接池、日志管理器等需要全局唯一对象的场景。常见的实现方式包括饿汉式、懒汉式、双重检查锁、静态内部类和枚举。线程安全问题可通过`synchronized`或双重检查锁解决,同时需防止反射和序列化破坏单例。优点是避免资源浪费,缺点是可能增加代码耦合度和测试难度。实际开发中应优先选择枚举或静态内部类,避免滥用单例,并结合依赖注入框架优化使用。
|
设计模式 存储 安全
设计模式2:单例模式
单例模式是一种创建型模式,确保一个类只有一个实例,并提供全局访问点。分为懒汉式和饿汉式: - **懒汉式**:延迟加载,首次调用时创建实例,线程安全通过双重检查锁(double check locking)实现,使用`volatile`防止指令重排序。 - **饿汉式**:类加载时即创建实例,线程安全但可能浪费内存。 示例代码展示了如何使用Java实现这两种模式。
329 4
|
设计模式 存储 安全
设计模式-单例模式练习
单例模式是Java设计模式中的重要概念,确保一个类只有一个实例并提供全局访问点。本文详解单例模式的核心思想、实现方式及线程安全问题,包括基础实现(双重检查锁)、懒汉式与饿汉式对比,以及枚举实现的优势。通过代码示例和类图,深入探讨不同场景下的单例应用,如线程安全、防止反射攻击和序列化破坏等,展示枚举实现的简洁与可靠性。
226 0
|
设计模式 存储 前端开发
前端必须掌握的设计模式——单例模式
单例模式是一种简单的创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点。适用于窗口对象、登录弹窗等场景,优点包括易于维护、访问和低消耗,但也有安全隐患、可能形成巨石对象及扩展性差等缺点。文中展示了JavaScript和TypeScript的实现方法。
672 13
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
236 2
|
设计模式 Java 数据库连接
Java编程中的设计模式:单例模式的深度剖析
【10月更文挑战第41天】本文深入探讨了Java中广泛使用的单例设计模式,旨在通过简明扼要的语言和实际示例,帮助读者理解其核心原理和应用。文章将介绍单例模式的重要性、实现方式以及在实际应用中如何优雅地处理多线程问题。
260 4
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
|
设计模式 存储 数据库连接
PHP中的设计模式:单例模式的深入理解与应用
【10月更文挑战第22天】 在软件开发中,设计模式是解决特定问题的通用解决方案。本文将通过通俗易懂的语言和实例,深入探讨PHP中单例模式的概念、实现方法及其在实际开发中的应用,帮助读者更好地理解和运用这一重要的设计模式。
209 1

热门文章

最新文章