码迷,mamicode.com
首页 > 其他好文 > 详细

设计模式:单例模式

时间:2015-09-13 20:01:48      阅读:117      评论:0      收藏:0      [点我收藏+]

标签:

概述:像Windows系统的任务管理器一样,你无论打开多少次,始终显示的一个窗口。如何保证一个类只有一个实例并且这个实例易于被访问呢,定义一个统一的全局变量可以确保对象随时可以被访问,但不能防止创建多个对象。一个最好的办法就是让类自身负责创建和保存它的唯一实例,并保证不创建其他实例,它还提供了一个访问该实例的方法,这就是单例模式的动机。。一点都不鸡冻-_-||。。

单例模式的定义:

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

  Singleton Pattern:Ensure  a class has only one instance, and provide a global point of access to it.

  单例模式是一种对象创建型模式。单例模式有三个要点:一是某个类只有一个实;二是它必须自行创建这个实例;三是它必须像整个系统提供这个实例。

单例模式的结构:

  单例模式是结构最简单的设计模式,它只包含一个类,即单例类。

技术分享

单例模式的实现:

    public class SingletonPattern
    {
        //静态私有成员变量
        private static SingletonPattern instance = null;

        //私有化构造函数
        private SingletonPattern() { }

        //静态私有工厂方法返回唯一实例
        public static SingletonPattern GetIstance()
        {
            if (instance == null)
                instance = new SingletonPattern();
            return instance;
        }
    }

  从代码可以看出在实现单例模式的时候,需要注意一下三点:

    1:私有化构造函数private

    2:提供一个自身静态私有成员变量

    3:提供一个公有的静态工厂方法

  饿汉式单例(Eager Singleton):

    技术分享

  一:饿汉模式,代码如下图所以:

    public class EagerSingleton
    {
        private static EagerSingleton instance = new EagerSingleton();
        private EagerSingleton() { }    
        public static EagerSingleton GetInstance()
        {
            return instance;
        }
    }

  当类被加载的时候,静态变量instance会被初始化,此时类的私有构造函数会被调用,单例类唯一实例将被创建。

 

  二:懒汉模式
    与饿汉模式单例类相同的是,懒汉式单例类(Lazy Singleton)的构造函数也是私有的,与饿汉式单例类不同的是,懒汉式单例类第一次被引用时将自己实例化,在懒汉式单例类加载时不会将自己实例化。

技术分享

从图中可以看出在懒汉单例类中,不是定义在静态变量时实例化单例类,而是在第一次调用静态工厂的时实例化单例类。

  代码如下:

    public class LazySingleton
    {
        private static LazySingleton instance = null;

        //程序运行时创建一个静态只读的辅助对象
        private static readonly object syncRoot = new object();

        private LazySingleton() { }

        public static LazySingleton GetInstance()
        {
            //第一重判断,先判断实例是否存在,不存在再加锁处理
            if(instance == null)
            {
                //加锁的程序在某一时刻只允许一个线程访问
                lock (syncRoot)
                {
                    //第二重判断
                    if(instance == null)
                    {
                        instance = new LazySingleton();//创建单例实例
                    }
                }
            }
            return instance;
        }
    }

  从代码中可以看到加锁了,为什么加锁呢? 是因为懒汉式单例存在一个严重的问题:如果在高并发、多线程环境下实现懒汉式单例,在某一时刻可能会有多个线程需要使用单例对象,即会有多个线程同时调用GetInstance()方法,可能会造成多个实例对象,这将违背单例模式的设计意图。为了防止生成多个单例对象,需要使用lock关键字,lock关键字表示锁定的代码片段成为临界区,可以确保一个线程位于代码的临界区。另一个线程不能进入临界区。如果其他线程视图进入锁定的代码,则将一直等待,知道该对象被释放为止。

  饿汉式单例与懒汉式单例进行比较:

    饿汉式单例在类加载的时候就将自己实例化,它的优点在于无需考虑多个线程同时访问的问题,可以确保实例的唯一性。从调用速度来讲,由于单例对象一开始就得以创建,因此要优于懒汉式单例。但是无论系统在运行时是否需要使用该单例对象,由于在类加载时该对象就需要创建,因此从资源利用效率角度来京,饿汉式单例不急懒汉式单例,而且在系统加载时有序需要创建饿汉式单例对象,加载时间会比较长。

    懒汉式单例在第一次使用时创建,无需一直占用系统资源,实现了延迟加载,但是必须处理好多个线程同时访问的问题,特别是当单例类作为资源控制器,在实例化时必然会涉及资源的初始化,而资源的初始化需要耗费大量的事件,这意味着出现多线程同时首次引用类的几率变大,通过双重检查锁定等机制进行控制,这将导致系统性能受到影响。

单例模式的优缺点:

  优点(1):提供了对唯一实例的受控访问。

    (2):在系统内存中只存在一个对象,因此可以节约系统的资源,对于一些需要频繁创建和销毁的对象,使用单例模式无疑是提高了系统的性能。

    (3):单例模式允许可变数目的实例。基于单例模式可以进行扩展,使用与控制单例对象相似的方法获得指定个数的实例对象,既节约了系统资源,又解决了由于单例对象共享过多有损性能的问题(自行提供指定数目实例对象的类可成为多例类)

  缺点(1):由于单例模式没有抽象层,所以扩展起来很难。

    (2):单例类职责过重,在一定程度上违背了单一职责。因为单例类既提供了业务方法,又提供了创建对象的方法(工厂方法),将对象的创建和对象本身的功能耦合在一起。

    (3):垃圾回收机制,如果实例化的共享对象长时间不被利用,系统会认为它是垃圾,会自动销毁并回收资源。在下次利用时又将重新实例化,这将导致共享单例对象状态丢失。

单例模式的使用环境:

  单例模式作为一种目标明确、结构简单、理解容易的设计模式,在软件开发中使用频率相当高,在很多应用软件和框架中都得以广泛的使用。

  在以下情况可以考虑使用单例模式:

  1:系统只需要一个实例对象,例如Windows资源管理器,或者因为资源消耗太大而只允许创建一个对象

  2:客户调用类单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。

 

如饥似渴的读着23中设计模式,小弟不才,刚刚接触到设计模式,汗啊-_-||,面向对象,面向对象,面向对象。重要的事情说三遍,接下来洗澡吃饭,回来继续。

 

设计模式:单例模式

标签:

原文地址:http://www.cnblogs.com/songyaqi/p/Singleton.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!