本文参考自《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