Android设计模式学习日记04--单例模式


单例模式,可以说是GOF的23种设计模式中最简单的一个。
这个模式相对于其他几个模式比较独立,它只负责控制自己的实例化数量单一(而不是考虑为用户产生什么样的实例),很有意思,是一个感觉上很干净的模式,本人很喜欢这个模式。
android中很多地方都用到了单例模式,本文以输入法管理者InputMethodManager为例,展开分析。
单例模式,Singleton Pattern,能够以其特有的优势,替代系统中全局变量,应用非常广泛。

1.意图
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
热门词汇:单例 唯一 私有构造

2.结构

android中有很多系统级别的全局变量,如时间,输入法,账户,状态栏等等,android中对这些都直接或者有些间接用到了单例模式。
以输入法为例,把上图修改为实际情况:


非常的简单,但是有一点,从上面我们也看到了synchronized关键字,在多线程的环境下,单例模式为了保证自己实例数量的唯一,必然会做并发控制。
类似这种线程安全的单例,跨进程的单例,参数化的单例等等的情况,确实超出本文的范围,而且都涉及到很多东西,是一个很大的话题,不好展开。

3. 代码:

public final class InputMethodManager {
    staticfinal Object mInstanceSync =new Object();//同步
    //内部全局唯一实例
    staticInputMethodManager mInstance;
 
    //对外api
    staticpublic InputMethodManager getInstance(Context context) {
        returngetInstance(context.getMainLooper());
    }
     
    /**
     * 内部api,供上面的外部api调用
     * @hide 系统隐藏的api
     */
    staticpublic InputMethodManager getInstance(Looper mainLooper) {
        synchronized(mInstanceSync) {
            if(mInstance != null) {
                returnmInstance;
            }
            IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
            IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
            mInstance =new InputMethodManager(service, mainLooper);
        }
        returnmInstance;
    }
}


  客户端调用,比如contextimpl中的getSystemService()方法中如下调用:

class ContextImpl extends Context{
    @Override
    publicObject getSystemService(String name) {
        if(WINDOW_SERVICE.equals(name)) {
            //... ... 省略下面n个if,else if
        }else if(INPUT_METHOD_SERVICE.equals(name)) {
            //获取输入法管理者唯一实例
            returnInputMethodManager.getInstance(this);
        } else if(KEYGUARD_SERVICE.equals(name)) {
             //... ... 省略下面n个if,else if
        }else if(ACCESSIBILITY_SERVICE.equals(name)) {
            //又见单例,无处不在
            returnAccessibilityManager.getInstance(this);
        }else if(LOCATION_SERVICE.equals(name)) {
            //... ... 省略下面n个if,else if
        } else if(NFC_SERVICE.equals(name)) {
            returngetNfcManager();
        }
        returnnull;
    }
}


  非常简单,干净的一个模式。

4.效果
(1).创建型模式。
(2).对唯一实例的受控访问。
(3).避免全局变量污染命名空间。
(4).允许对操作和表示的精化。
(5).比类操作更灵活。 

特点

1,该类只有一个实例
2,该类自行创建该实例(在该类内部创建自身的实例对象),就是自己已经new了
3,向整个系统公开这个实例接口

单例模式的俩种方式:
饿汉式
class Singleton {
  private static Singleton instance=new Singleton();
  private Singleton(){}
  static Singleton getInstance() {
      return instance;
  }
}
对于资源密集,配置开销较大的单体更合理的做法是将实例化(new)推迟到使用它的时候
懒汉式
class Singleton {
  private static Singleton instance=null;
  private Singleton(){}
//公开,静态的工厂方法,需要使用时才去创建该单体
  public static Singleton getInstance() {
      if(instance==null)
      instance=new Singleton();
      return instance;
  }
}

单例模式在JS的应用 参考来自http://www.cnblogs.com/snandy/archive/2011/04/07/2007717.html



单例模式是Javascript最基本,最有用的模式之一。它提供了一种将代码组织为一个逻辑单元的手段,这个逻辑单元中的代码通过单一的变量进行访问。
单体在Javascipt中有许多用处,可以用来划分命名空间,以减少全局变量的泛滥。还可以用在分支技术中用来处理各浏览器的差异。
Javascript中单例模式的实现方式有多种,每一种都有自身的优点或缺点。

 

1,对象直接量实现最基本,最简单的单体

var Singleton = {
    attr1 : 1,
    attr2 : 'hello',
    method1 : function(){alert(this.attr2);},
    method2 : function(arg){}
}


这种方式中,对象所有成员都通过Singleton加点号访问。所有成员是公开的,没有私有的。在执行到变量Singleton时,会加载(实例化)自身,即非惰性加载。
此外method1用this访问单体的其它成员会存在一些风险,因为method1的上下文不是总是指向Singleton对象。
比如当把method1作为事件监听器时,this可能指向的是dom元素,这时可能会提示undefined。

 

2,闭包实现私有成员的单体

var Singleton = function(){
    var attr = 1, fn = function(){};
    return {
        method : function(){ fn(); },
        getAttr : function(){ return attr; }       
    }; 
}();


这种方式中var定义私有的成员属性attr,方法fn,然后返回一个公开的接口method和getAttr。今后修改实现时,接口方法method和getAttr不变,只需修改私有的attr和fn的具体实现。使用如下

?
1
2
Singleton.method();
Singleton.getAttr();

 

3,闭包实现私有成员的惰性实例化单体

?
var LazySingleton = function(){
    var attr = 1, fn = function(){};
    var obj = {
        method : function(){ fn(); },
        getAttr : function(){ return attr; }
    };
    function init(){
        return obj;
    }
    return {getInstace: init};
}();


 

适用场合上面已经提到:对于那些必须加载大量数据的单体直到需要使用它的时候才实例化。使用方式是这样的

?
1
2
LazySingleton.getInstance().method();
LazySingleton.getInstance().getAttr();

 

4,又发现另一种

?
1
2
3
4
5
6
7
function singleton() {
     var obj = new Object();
     singleton = function () {
         return obj;
     };
     return obj;
}

仅在第一次时会new,这个Object泛指自定义的所有类。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值