Android系统开发---设计模式之单例模式

来源:互联网 发布:网络40大禁书 编辑:程序博客网 时间:2024/05/18 01:12
1.单例模式(曾经沧海难为水,除却巫山不是云)
  定义:保证一个类,只有一个实例存在,同时提供能对该实例加以访问的全局访问方法。
        单例模式是一种对象创建型模式,使用单例模式可以保证为一个类只生成唯一的实例对象。也就是说,在整个程序空间中,该类只存在一个实例
  对象。单例模式的要有三个:1)某个类只有一个实例;2)它必须自行创建这个实例;3)它必须自行向整个系统提供这个实例
English definition:Ensure a class only has one instance,and provide a global point of access to it.


   2.单例模式深入分析
         单例模式适合于一个类只有一个实例的情况,如窗口管理器,打印缓冲池和文件系统,它们都是原型的例子。典型的情况是,那些对象的类型被遍及一个
     软件系统的不同对象访问,因此需要一个全局的访问指针,这便是众所周知的单例模式的应用。
         注意:使用单例模式时,构造函数一定是private类型的。
         在计算机系统中,需要管理的资源包括软件外部资源,例如,每台计算机可以有若干个打印机,但是有一个Printer Spooler,以避免两个打印作业同时
     传输到传真卡中的情况。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。需要管理的软件
     内部资源包括负责记录网站来访人数的部件,记录软件系统内部事件、出错信息的部件,或是对系统的表现进行检查的部件等,这些部件都必须集中管理。


3.单例模式形式分析

1)单例模式的第一个版本,采用的是"饿汉式",也就是当类加载进来时就立即实例化当前类的对象,这种方式比较消耗计算机的资源,代码如下:

package com.example.singleton;


public class SingletonOne {

public static final SingletonOne singletonOne=new SingletonOne();

private String name;

public String getName(){
return name;
}

public void setName(String name){
this.name=name;
}

private SingletonOne(){

}

public static SingletonOne getSingletonOne(){
return singletonOne;
}
}

2) 单例模式提供的第二个版本,"懒汉式",在单线程中能够非常好的工作,但是在多线程中存在线程安全问题。

package com.example.singleton;


public class SingletonTwo {

private String name;
private static SingletonTwo singletonTwo;

public String getName(){
return name;
}

public void setName(String name){
this.name=name;
}

private SingletonTwo(){

}

public static SingletonTwo getSingletonTwo(){
if(null == singletonTwo){
singletonTwo = new SingletonTwo();
}
return singletonTwo;
}
}



3)为解决多线程问题,采用对函数进行同步的方式,但是比较浪费资源,因为每次都要进行同步检查,而实际中真正需要好只是在第一次实例化时检查
   ,具体代码如下所示:

package com.example.singleton;


public class SingletonThree {

private String name;
private static SingletonThree singletonThree;

public String getName(){
return name;
}

public void setName(String name){
this.name=name;
}

private SingletonThree(){

}

public static synchronized SingletonThree getSingletonThree(){
if(null == singletonThree){
singletonThree = new SingletonThree();
}
return singletonThree;
}
}


4) 既可以解决懒汉式,又可以解决多线程问题,还可以资源浪费的现象,看上去是一种不同的选择

package com.example.singleton;


public class SingletonFour {

private String name;
private static SingletonFour singletonFour;

public String getName(){
return name;
}

public void setName(String name){
this.name=name;
}

private SingletonFour(){

}

public static SingletonFour getSingletonFour(){

if(null == singletonFour){
synchronized(SingletonFour.class){
if(null == singletonFour){
singletonFour = new SingletonFour();
}
}
}
return singletonFour;
}
}


测试代码如下:

package com.example.test;


import com.example.singleton.SingletonFour;


public class Test {

public static void main(String[] args){
SingletonFour singleOne=SingletonFour.getSingletonFour();
SingletonFour singleTwo=SingletonFour.getSingletonFour();
singleOne.setName("First");
singleTwo.setName("Second");
System.out.println(singleOne.getName());
System.out.println(singleTwo.getName());
}
}


测试结果:
Second
Second

4.单例模式的优缺点分析
  优点:客户端使用单例模式类的实例时,只需要调用一个单一的方法即可生成一个唯一的实例,节省资源。
  缺点:首先,单例模式很难实现序列化,这就导致单例模式的类很难被持久化,当然,也很难通过网络传输;其次,由于单例模式采用静态方法,无法在继承结构
        中使用;最后,如果在分布式集群的环境中存在多个java虚拟机的情况下,具体确定哪个单例模式在运行也是很困难的事情。
5.应用
  单例模式一般出现在以下几种情况中:
  1)在多个线程之间,如servlet环境,共享同一个资源或者操作同一个对象。
  2)在整个程序空间使用全局变量共享资源
  3)在大规模系统中,为了性能的考虑,需要节省对象的创建时间等。


6.Android系统中的单例模式
  Android系统中的单例模式无处不在。例如,对服务的管理者ServiceManager就采用了单例模式,具体代码如下

public final class ServiceManager{
   private static final String TAG="ServiceManager";
   private static IServiceManager sServiceManager;
   private static IServiceManager getIServiceManager(){
       if(null != sServiceManager){
        }
   }
......
}

在Android系统源代码中还出现一处代码如下:

public final classInputMethodManager{
    static final Object mInstanceSync = new Object();
    static InputMethodManager mInstance;
    static public InputMethodManager getInstance(Looper mainLooper) {
        synchronized (mInstanceSync) {
            if (mInstance != null) {
                return mInstance;
            }
            IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
            IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
            mInstance = new InputMethodManager(service, mainLooper);
        }
        return mInstance;
    }
}


原创粉丝点击