本文参考自《Java与模式》
以及http://baike.baidu.com/view/1859857.htm
一、单例类的特点
1.某个类只能有一个实例。
2.构造器是private的(因此,单例类不能被继承)。
3.单例类必须自行创建自己的唯一实例。
二、单例的分类
1.饿汗式单例类
a.类图
b.Code
package com.jue.dp; public class EagerSingleton { private static final EagerSingleton instance = new EagerSingleton(); private EagerSingleton() { } public static EagerSingleton getInstance() { return instance; } }
2.懒汉式单例类
a.类图
b.Code
package com.jue.dp; public class LazySingleton { private static LazySingleton instance; private LazySingleton() { } public synchronized static LazySingleton getInstance() { if (instance == null) { instance = new LazySingleton(); } return instance; } }
3.双重检测
package com.jue.dp; public class DoubleLockSingleton { private static DoubleLockSingleton instance; private DoubleLockSingleton() { } public static DoubleLockSingleton getInstance() { if (instance == null) { synchronized (DoubleLockSingleton.class) { if (instance == null) { instance = new DoubleLockSingleton(); } } } return instance; } }
三、使用场景
1.一个系统要求一个类只有一个实例的时候。
2.整个项目需要一个共享访问点。
四、单例类的应用
Java.lang.Runtime对象
1.每个java应用程序里面都有唯一的一个 Runtime对象。
2.这个Runtime对象能够与器运行环境发生相互作用。
3.Runtime对象能够执行外部命令,查询内存信息,gc,加载动态库。
五、优点
1.保证了全局唯一。
2.内存中只有一个实例,减少了内存开支。
3.提供了一个全局访问点。
六、缺点
1.通过反射依然可以可以生成两个实例。
本文参考自《设计模式之禅》,《Java与模式》
一、通过给出一个原型对象来指明所要创建的对象的类型。
二、Java中半支持
1.Ojbect类提供一个clone方法。
2.Java必须实现Cloneable来显式表明Javabean支持复制。
3.如果不实现Cloneable接口而直接使用,会抛出java.lang.CloneNotSupportedException。
4.默认的实现是浅拷贝,需要重写clone方法。
三、Code
package com.jue.dp; public class TV implements Cloneable { private int price; private Box box; public TV(Box b, int price) { this.box = b; this.price = price; System.out.println("TV()"); } public Box getBox() { return box; } public void setBox(Box box) { this.box = box; } void display() { System.out.println(box.name + " , " + price); } @Override protected TV clone() throws CloneNotSupportedException { TV temp = (TV) super.clone(); temp.box = box.clone(); return temp; } }
package com.jue.dp; public class Box implements Cloneable { public String name = "default"; @Override protected Box clone() throws CloneNotSupportedException { return (Box) super.clone(); } }
package com.jue.dp; public class MainClass { public static void main(String[] args) throws CloneNotSupportedException { Box b1 = new Box(); TV t1 = new TV(b1, 100); t1.display(); System.out.println("------------------------"); TV t2 = t1.clone(); t2.display(); System.out.println("------------------------"); b1.name = "changed"; t1.display(); t2.display(); } }
四、优点
1.原型模式是在内存中二进制流的拷贝,比直接new一个对象性能要好很多。
2.直接在内存中拷贝,构造函数不会执行。
3.能够获取一个即时状态的值。
五、缺点
1.构造器不会执行。
六、注意点
1.Object的clone如果只是调用super.clone,复合类型只是浅拷贝(对象中的数组对象,其他复合对象,但是String是深拷贝)。
2.Clone与final常量有冲突,如下有编译错误。
package com.jue.dp; import java.util.ArrayList; public class Things implements Cloneable { private final ArrayList<String> arraylist = new ArrayList<String>(); @Override protected Object clone() throws CloneNotSupportedException { Things t = (Things) super.clone(); t.arraylist = (ArrayList<String>) this.arraylist.clone(); return super.clone(); } }
七、使用场景
1.类的初始化需要较多资源。
2.需要记录一个状态的对象的值。
3.使用new需要较为繁琐的准备和访问权限使用受限。
以下几篇文章是较深入分析binder机制。
目录
1. Android - Binder机制 - ServiceManager
2. Android - Binder机制 - 普通service注册
3. Android - Binder机制 - 获得普通service
4. Android - Binder机制 - client和普通service交互
5. Android - Binder机制 - Binder框架总结
6. Android - Binder机制 - ProcessState和IPCThreadState
7. Android - Binder机制 - 驱动
初看IPCThreadState代码一头雾水,之所以复杂,是因为IPCThreadState的代码一部分给客户端使用,一部分给服务端使用,两个一掺杂,所以就乱了。如socket编程,客户端和服务端有很多一样的操作(如打开socket、read、write、close等),也有一些不一样的操作(如服务端多了listen和accept,客户端多了connect),如果我们将服务端和客户端的代码写在一起,如果你不懂socket编程,肯定会觉得很复杂。但是,如果我们先定义一个基类来完成服务端客户端相同的操作,然后再创建两个继承类,分别执行服务端和客户端不一样的操作,相信这样让程序员一眼就能看出其中的关系。IPCThreadState就是因为将服务端和客户端写在了一起,所以显得比较复杂。
IPCThreadState主要的函数有sendReply、waitForResponse、joinThreadPool、transact、talkWithDriver、writeTransactionData、executeCommand等。下面我们分析IPCThreadState的服务端和客户端的流程和使用了上面哪些主要函数,你会发现这些大部分函数或者只为客户端使用或者只为服务端使用。
初始化
打开一个socket,bind要监听的端口号和ip地址
变为服务端
执行listen,一个普通(默认是客户端)的socket就变为了服务端
监听
执行accept
接收数据
recv数据
处理数据
根据业务进行相关处理
反馈数据
Send数据
关闭
执行Close
初始化
打开binder设备,如sp<ProcessState> proc(ProcessState::self())里执行了open_binder函数。
变为服务端
执行AddService,如CameraService::instantiate()
监听
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
这俩其实都是起监听的作用,binder不像socket只有一个监听,binder可以支持很多监听线程,ProcessState::self()->startThreadPool()其实也是调用的IPCThreadState::self()->joinThreadPool()。joinThreadPool里循环调用talkWithDriver,该函数其实就是扫描设备是否有数据。
接收数据
接收数据和监听是在一起的,这里其实很像UDP的socket编程,UDP是没有accept步骤的。
反馈数据
executeCommand对各种指令进行处理,该函数会在后面详解。
executeCommand处理的时候有些需要反馈的数据写到mOut缓冲,那什么时候发送mOut的数据呢,其实还是joinThreadPool的talkWithDriver,也就是在这可以看出joinThreadPool同时干两个事,一个是接收数据,一个是发送数据。
关闭
Close(mProcess->mDriverFD)
打开一个socket
连接服务端
执行connect
发送请求
send数据
接收反馈
recv数据
关闭
执行Close
打开binder设备,如camera客户端在哪打开的呢,看看getCameraService函数里面为了获得服务,先获得ServiceManager的函数defaultServiceManager(),该函数执行了ProcessState::self()->getContextObject(NULL),ProcessState::self()就会打开binder设备。
连接服务端
执行GetService,通过ServiceManager获得了服务的Handle,以后就是靠这个Handle和服务端打交道的,就想socket的整数句柄。另外,客户端业务层并不直接使用Handle,而使用了Bpxxx,它是服务端在客户端的代理(只是为了客户端写代码更方便)。
发送请求
执行remote()->transact,而实际是执行的IPCThreadState::transact,该函数又执行了writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL),从函数名上可以看出是将转发的数据写入binder,又一次注意参数handle,它指定哪个服务端来处理。
接收反馈
IPCThreadState::transact发送请求后接着执行waitForResponse(reply),从函数名上可以看出是等待反馈。
关闭
执行Close