对象和函数

来源:互联网 发布:整型变量的数据范围 编辑:程序博客网 时间:2024/05/01 03:47

以一个播放器Player为例子,他可能有以下几个函数接口:

1,open;2,close;3,start;4,stop;5,write

其实根本用不了这么多函数,只需要一个函数也能完成功能,这个函数可以这样定义SendMsg(void* param),只有一个参数,param作为一块内存,一次存放的数据是消息类型(表示是open还是close等)、数据的长度、真实的数据。SendMsg根据不同的消息类型选择不同的处理方式。这种方法是面向对象所鄙视的,主要原因是没有接口的抽象;不同通过函数名就表达出函数的功能;不能充分发挥编译器的功能,例如param参数有误,编译会通过,但是open函数的参数格式以及函数名写错,编译器会纠错。此外还有一个缺点,多传了数据,并通过传的消息类型做处理,如果是用良好的函数名调用则编译器会决定调用哪个函数,而不需要判断。

但是简单的一个SendMsg函数就没有用了吗?考虑进程间通信。编译器所能编译的只是一个模块,即编译器不会知道另一个进程的存在。各种各样的偏底层的进程通信都是SendMsg这样的方式。假设系统中存在一个service,专门处理各个播放器发送的数据,混音并播放,SendMsg的方式可以很好地解决这个问题。但是这只是底层,仍然可以通过封装来定义良好的接口,即在Player和Service之间引入两个代理对象,PlayerProxy和ServiceProxy,PlayerProxy定义接口1,open;2,close;3,start;4,stop;5,write;6,SendMsg;ServiceProxy定义接口1,open;2,close;3,start;4,stop;5,read;6,GetMsg;7,isopen;8,isstart。一个Player对应一个PlayerProxy和一个ServiceProxy。Player调用write,进而调用PlayerProxy的write,进而调用SendMsg。Service调用read,进而调用ServiceProxy的read进而调用GetMsg,从而可以得到Player的write的数据。Player调用open可导致ServiceProxy的isopen返回True。Service会注册每一个ServiceProxy,Service根据ServiceProxy的isopen返回值决定是否使对应Player的数据参与混音。当Player调用close,会引起Service注销一个ServiceProxy。这样,Player的设计者压根就不需要考虑进程通信,也完全可以不考虑Service的存在。中间添加的代理可以抽象出来,做成一个可以复用的模块,貌似android的进程通信方式Binder就是这么做的。