最简单的一个模式
定义:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
自我定义:一个应用应该只有一个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、单例模式与单一职责原则有冲突。