设计模式(4)单例模式(讲解+应用)

目录android

  1. 单例模式数据库

  2. 为何使用单例模式设计模式

  3. 单例模式实际应用缓存

单例模式

这个设计模式应该算是我最先接触到一个,也是从那个时候知道有一种东西叫设计模式,看到这种代码结构,有种将好的东西经过某种精美的包装进行包装同样,似锦上添花。网络

单例模式:单例模式中有一个单例类的结构,来保证系统中,该类只可以被实例化一个,经过这种方式控制系统中实例的个数,同时易于外界访问。多线程

为何使用单例模式

对于缓存,数据库链接,网络请求队列等,资源消耗比较大的,一般咱们只是须要一个实例,来减小资源的消耗。
为何不实用静态全局变量来进行控制呢?
经过静态全局变量持有一个咱们建立的实例,而后对这个实例进行一些操做不也是能够保证单例吗?这种方式彷佛要比多出一个设计模式去改变类的结构方便的多,可是咱们却不会这样去作,缘由就是线程

  1. 当咱们设置一个全局的变量在系统中,其会致使出现命名空间污染现象,致使咱们在一些引用的过程当中,出现了将全局变量做为局部变量使用的状况,设计

  2. 同时若是咱们对于静态全局变量若是不加锁的话,很容易在多线程操做的过程当中带来同步上的一些问题,code

  3. 最后一个缘由就是若是咱们将其做为一个静态全局变量使用,那么咱们就没法实现一个惰性建立实例,对于过于消耗资源的实例,经过惰性建立,咱们将其拖延至使用时建立,而不会过早的消耗资源。对象

单例模式的实际应用

到了看一下单例模式庐山真面目的时候了,首先经过一段简单的Java代码看一下其大致结构。

public class Singleton{
    private static Singleton mSingleton = null;
    private Singleton(){

    }
    public static Singleton getInstance(){
        if(mSingleton==null)
            mSingleton = new Singleton();
        return mSingleton;
    }
}

上面是一个简单单例模式的示范代码,经过这个代码,咱们能够看出单例类的构造方法是私有方法,也就是该类咱们没有办法经过new获得的,只可以经过静态的getInstance()方法获得。可是对于多线程问题,若是有多个线程在执行这个方法,那么可能就会有多个实例被建立出来,如何应对这个问题呢?

1.对该代码区域进行同步

public class Singleton{
    private static Singleton mSingleton = null;
    private Singleton(){
    }
    public synchronized Singleton static getInstance(){
        if(mSingleton==null)
            mSingleton = new Singleton();
        return mSingleton;
    }
}

当咱们对代码块进行加锁以后,一个线程就要等到另外一个线程结束以后,才能够继续执行该区域代码,可是当咱们对一个代码区域进行加锁以后,咱们的代码效率就会下降100倍。对这个代码区域进行同步以后,每当咱们执行这块代码,都将会出现一个等待。
2.急切建立实例,而不是采用惰性建立

public class Singleton{
    private static Singleton mSingleton = new Singleton();
    private Singleton(){

    }
    public synchronized Singleton static getInstance(){
        return mSingleton;
    }
}

经过急切建立在对类进行初始化的时候就实例化了类,就不会出现多个线程竞争的问题,可是会致使的问题是若是建立实例消耗过大的时候就会出现提早消耗资源的问题。所以咱们常采用的一种方法是双重加锁法。
3.双重检查加锁

public class Singleton{
    private static Singleton mSingleton = null;
    private Singleton(){

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

这种方式对于加锁不是对整个方法进行加锁,而是判断当这个单例未被初始化以后,才对这个实例的初始化区域进行一个同步,在同步的过程当中在进行一个是否实例化的判断。即所谓的双重检查。课有疑问的在于,咱们已经进入了同步区域了,为何还要对其作一个判断呢?就是当两个线程同时越过了第一个判断以后,若是咱们在同步方法中没有对与实例的判断,这个时候,咱们就有可能出现实例被建立两次的状况。
综上所述:综合效率,资源消耗等来看,经过双重检查加锁的方式来建立最为方便。
单例模式在android中有那些应用呢?
android中有不少系统级别的全局变量,如时间,输入法,帐户,状态栏等等
InputMethodManager类,CalendarDatabaseHelper类、Editable类等等。在这些类中,都存在一个方法getInstance,在该方法或直接返回对象的引用或判断一个类的引用是否为NULL,若不为NULL,则直接返回该引用,若为NULL,则new一个新的对象,并返回。例如,对于CalendarDatabaseHelper类,存在以下的代码:

public static synchronized CalendarDatabaseHelper getInstance(Contextcontext)  
{  
    if (sSingleton == null)  
    {  
       sSingleton = newCalendarDatabaseHelper(context);  
    }  
        return sSingleton;  
}

下一篇文章将更新关于装饰器设计模式相关的

相关文章
相关标签/搜索