1.4 Android 的 IPC interface.
C++和Java 的接口都只支持进程内的调用。为了支持专门用于跨进程的接口调用,Android 专门做了一些规定。
凡是以IXXXX 定义的接口类均可以支持IPC(当然,进程内也可以调用IXXXX定义的接口)。
当我们在图中看到一个IXXX 接口类,我们便可以认为这是一个进程的边界,他的实现端和调用端对象运行在不同的进程里(至少是不同的线程)。
如上图中,IWindow的两端W对象 和 WindowState 对象就用不同的颜色来标明它们分属于不同的进程,W运行在应用程序的进程里,而WinState存在与System Server 进程里。
1.5 Aggregation
聚合表达了两个类的从属关系,但和Composition不同,他们的生命周期并不一样。
一个经典的例子就是工厂和车子,车子是工厂造出来的,工厂倒闭了,车子可以继续开,反之亦然。
图中PolicyManager 和 PhoneWindow就是类似的关系。
1.6 Inherritance
就是最常见的继承关系了。
复杂的继承关系很难阅读和记忆,通过UML图则方便很多,你可以清楚到看出继承关系,同时能够理解继承的设计思想。
比如说图中右上角,PhoneWindow 继承了Window 类,Activity 引用的是其基类Window的对象,但背后真正干事的是PhoneWindow对象, 因为Acitivy 用的Window类对象是PolicyManager构造出来的。通过这种方式,PhoneWindow的实现细节被PolicyManager 和 Window 基类隐藏起来,从而大大降低了应用程序(Activity) 改变的几率。
这个正是设计模式里有名的工厂模式之一。
1.7 依赖
依赖不同于引用,依赖者和被依赖着之间没有直接的对象引用,通常是常量或静态方法的使用。
比如图中,Activity使用了PolicyManager类的静态方法 makeNewWindow() 创建了PhoneWindow对象,我们说Acitivy 依赖PolicyManager 这个模块,但它并没有引用PoclicyManager的对象。
依赖通常用一根单向虚线箭头表示。
2. 时序图
通过时序图,我们可以了解代码的调用流程, 并可以检查调用过程中可能产成的潜在问题,如死锁等。
时序图可以从两个方向去看,纵向和横向。
纵向描述了一个对象在时间轴上所做的事情,一个方块通过代表一个函数的调用。
横向则描述了各个对象之间的调用关系, 包括同步调用,异步调用,返回等等。
此外,在时序图中,我们可以给执行块赋予不同的颜色,代表了他们分别运行在不同的进程或线程里。
下面就是一张时序图的例子,它描述了Android中一个System server 进程启动的过程, 图中的粉红色注释列举了从图中我们可以获知的一些信息。
刚才不是说从时序图中能看出死锁? 就这样一样图?夸张了吧! 没错,看看下面一个例子吧!