Android单例设计模式简介和实例

最简单的一个模式

定义:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
自我定义:一个应用应该只有一个ImageLoader实例
优点 : 减少内存开支
缺点 :扩展难,与单一职责违背

UML图

这里写图片描述

简单实例:一个公司只有一个CEO

(简单来说就是只能调用getCEO方法获得已有CEO类,不能newCEO类。)
   package com.dp.example.singleton;  
    /** 
     * 人的基类 (抽象)
     * @author mrsimple 
     * 
     */  
    public abstract class Person {  
        public abstract void talk() ;  
    }  

    // 普通员工  
    public class Staff extends Person {  
        @Override  
        public void talk() {}  
    }  

    // 副总裁  
    public class VP extends Person {  
        @Override  
        public void talk() {}  
    }  

    // CEO,方法一:实现单例模式(不常用,漏洞多)  
    public class CEO extends Person {  
        // 静态实例化CEO
        private static final CEO mCeo = new CEO();  

        private CEO() {  
        }  
        // 方法私有
        public static CEO getCeo() {  
            return mCeo;  
        }  

        @Override  
        public void talk() {  
            System.out.println("CEO发表讲话");  
        }  
    }  

    // 公司类  
    import java.util.ArrayList;  
    import java.util.List;  

    public class Company {  
        private List<Person> allPersons = new ArrayList<Person>();  

        public void addStaff(Person per) {  
            allPersons.add(per);  
        }  

        public void showAllStaffs() {  
            for (Person per : allPersons) {  
                System.out.println("Obj : " + per.toString());  
            }  
        }  
    }  

    // test  验证类
    public class Test {  
        public static void main(String[] args) {  
            Company cp = new Company() ;  
            Person ceo1 = CEO.getCeo() ;  
            Person ceo2 = CEO.getCeo() ;  
            cp.addStaff(ceo1);  
            cp.addStaff(ceo2);  

            Person vp1 = new VP() ;  
            Person vp2 = new VP() ;  

            Person staff1 = new Staff() ;  
            Person staff2 = new Staff() ;  
            Person staff3 = new Staff() ;  

            cp.addStaff(vp1);  
            cp.addStaff(vp2);  
            cp.addStaff(staff1);  
            cp.addStaff(staff2);  
            cp.addStaff(staff3);  

            cp.showAllStaffs();  
        }  
    }  

常见的实现方式:

package com.dp.example.singleton;  

public class Singleton {  
    // 静态实例化
    private static Singleton mInstance = null;  

    private Singleton() {  

    }  

    public void doSomething() {  
        System.out.println("do sth.");  
    }  

    /** 常用
     * 方式二、double-check-lock, 避免并发时创建了多个实例, 该方式不能完全避免并发带来的破坏. 
     * @return 
     */  
    public static Singleton getInstance() {  
        if (mInstance == null) {  
            synchronized (Singleton.class) {  
                if (mInstance == null) {  
                    mInstance = new Singleton();  
                }  
            }  
        }  
        return mInstance;  
    }  

    /** 常用
     * 方式三 : 在第一次加载SingletonHolder时初始化一次mOnlyInstance对象, 保证唯一性, 也延迟了单例的实例化, 
     * 如果该单例比较耗资源可以使用这种模式. 
     *  
     * @return 
     */  
    public static Singleton getInstanceFromHolder() {  
        return SingletonHolder.mOnlyInstance;  
    }  

    /** 
     * 静态内部类 
     *  @author mrsimple 
     */  
    private static class SingletonHolder {  
        private static final Singleton mOnlyInstance = new Singleton();  
    }  

    /** 
     *  方式四 : 枚举单例, 线程安全 
     * @author mrsimple  
     */  
    enum SingletonEnum {  
        INSTANCE;  
        public void doSomething() {  
            System.out.println("do sth.");  
        }  
    }  

    /** 
     * 方式五 : 注册到容器, 根据key获取对象.一般都会有多种相同属性类型的对象会注册到一个map中 
     * instance容器 
     */  
    private static Map<string singleton=""> objMap = new HashMap<string singleton="">();  
    /** 
     * 注册对象到map中 
     * @param key 
     * @param instance 
     */  
    public static void registerService(String key, Singleton instance) {  
        if (!objMap.containsKey(key) ) {  
            objMap.put(key, instance) ;  
        }  
    }  

    /** 
     * 根据key获取对象 
     * @param key 
     * @return 
     */  
    public static Singleton getService(String key) {  
        return objMap.get(key) ;  
    }  

}  
源码分析

在Android系统中,我们经常会通过Context获取系统级别的服务,比如WindowsManagerService, ActivityManagerService等,更常用的是一个叫LayoutInflater的类, 这些类以单例的形式注册在系统中,我们需要的时候就通过Context的getSystemService(String key)获取。我们以LayoutInflater为例来说明, 平时我们使用LayoutInflater较为常见的地方是在ListView的getView方法中。

大神的文章单例设计模式在Android中的运用

优点与缺点

优点 : 减少内存开支
1、由于单例模式在内存中只有一个实例,减少了内存开支,特别是一个对象需要频繁地创建、销毁时,而且创建或销毁时性能又无法优化,单例模式的优势就非常明显。
2、由于单例模式只生成一个实例,所以减少了系统的性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后用永久驻留内存的方式来解决;
3、单例模式可以避免对资源的多重占用,例如一个写文件动作,由于只有一个实例存在内存中,避免对同一个资源文件的同时写操作。
4、单例模式可以在系统设置全局的访问点,优化和共享资源访问,例如可以设计一个单例类,负责所有数据表的映射处理。

缺点 :扩展难,与单一职责违背
1、单例模式一般没有接口,扩展很困难,若要扩展,除了修改代码基本上没有第二种途径可以实现。
2、单例模式与单一职责原则有冲突。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值