隐藏erlang中常见接口背后的不同实现

我有一段erlang代码,它应该读取db中的一些值,并且应该支持几个dbs.我希望我的代码在某种程度上不依赖于db,所以我实现了两个不同的gen_servers,它们使用相同的atom(db_handler)注册.我决定应该从哪个版本开始读取.app文件.

这两个gen_servers暴露了一个常见的handle_call,所以我可以在我的应用程序的其他部分使用类似的东西:

gen_server:call(db_handler, {do_something, "value1", "value2"})

这有效,但它仍然强烈地耦合到这样一个事实,即新数据库的每个和任何未来实现都应该是gen_server.

我在考虑使用!运算符并处理handle_info中的命令,但我认为可能有更好的解决方案(可能通过另一个模块?).

有人能给我一些关于在erlang中处理这类事情的更好方法的见解吗?

最佳答案 对于每个数据库服务器,添加一个公共接口来抽象调用:

-module(db_server1).

...

do_something([Value1,Value2]) -> gen_server:call(db_handler, {do_something, "value1", "value2"}).

...

另一个不使用gen服务器

-module(db_server2).

...

do_something([Value1,Value2]) -> something_else({do_something, "value1", "value2"}).

...

创建一个新进程(gen_server:o),它接收作为init参数的param,用于选择db服务器并将其存储在其状态中(例如db_server2),

对于每个do_something函数,实现如下函数:

do_something(Value1,Value2) -> gen_server:call(db_handler, {do_something, ["value1", "value2"]}).

...

handle_call({Func, Args}, _From, DB_server) ->
    R = DB_server:F(Args),
    {reply, R, DB_server}.

使用强制转换或等效的非阻塞接口也是如此

点赞