回调(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>}