回调(callback)是编程中经常会用到的一种模式,在 elixir 中我们通常通过假定一个些模块里面包含了一些符合特定函数签名的函数定义,或者说这个模块实现了某种 behaviour,来进行回调编程。这种编程模式的好处是可以将回调的实现模块进行升级或者替换,而不改变回调的函数签名,从而不破坏调用者的代码。
在 Supervisor 启动时,我们需要提供 children 模块的列表,这里其实也可以使用回调:child_spec/1
来实现。我们来测试一下:
defmodule O1 do
# 我们假装启动了一个进程
def fake_start(arg) do
IO.puts("Starting with arg: #{inspect(arg)}!")
{:ok, self()}
end
# 这里是两个 Child 的模块,都实现了 `child_spec/1` 回调
defmodule Alice do
def child_spec(arg) do
%{
id: __MODULE__,
start: {O1, :fake_start, [arg]}
}
end
end
defmodule Carl do
def child_spec(arg) do
%{
id: __MODULE__,
start: {O1, :fake_start, [arg]}
}
end
end
def test do
children = [
# 第二个元素即是传给启动函数的参数
{Alice, "hi"},
# 默认的参数是 `[]`
Carl
]
Supervisor.start_link(children, strategy: :one_for_one)
end
end
运行一下,可以看到 Supervisor 启动成功。回调编程是一种简单且被广泛应用的设计模式。在 erlang 和 elixir 中,更是被应用到了极致。
iex(5)> O1.test
Starting with arg: "hi"!
Starting with arg: []!
{:ok, #PID<0.345.0>}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。