用OTP构建系统
通用事件处理
时间是已经发生的事情,在event_handler.erl中,发生一个事件,会发送一个event消息给注册进程,在这个过程中,发送消息后并不需要去关心它会如何去处理,只是把消息发送出去,告诉其他进程发生了什么,这种把事件转向事件接收器的进程叫做事件处理器。
event_handler.erl
-module(event_handler).
-author("chen").
%% API
-export([make/1, add_handler/2, event/2]).
make(Name)->
register(Name,spawn(fun() -> my_handler(fun no_op/1) end )).
add_handler(Name,Fun) -> Name ! {add, Fun}.
%%生成一个事件
event(Name, X) -> Name ! {event, X}.
my_handler(Fun)->
receive
{add, Fun1} ->
my_handler(Fun1);
{event, Any}->
(catch Fun(Any)),
my_handler(Fun)
end.
no_op(_) -> void.
event_handler:make(Name)是创建一个名字是一个原子的进程,用接受发送的消息。
event_handler:event(Name, X)是将消息X发送到事件处理中,
event_handler:add_handler(Name, Fun)执行这个方法,当事件X发生时,事件处理器就会去执行函数Fun(X)。
当需要事件处理器能够处理事件,就需要编写一个回调模块来安装到事件处理器中。如下为一个事件处理器的回调模块。
motor_controller.erl
-module(motor_controller).
-author("chen").
%% API
-export([add_event_handler/0]).
add_event_handler()->
event_handler:add_handler(errors, fun controller/1).
controller(too_hot)->
io:format("Turn off the motor ~n");
controller(X)->
io:format("~w ignored event: ~p~n",[?MODULE ,X]).
执行结果:
在上述过程当中,通过提供一个名称来作为接收消息的地方(注册进程),通过定义一种协议来给这个注册进程发送事件。可以通过安装自己定义的事件处理器,来对事件进行处理。这样可以做到将事件的产生和处理分离开来,对于那些产生事件后并不处理时,可以不影响事件的产生。