在erlang中的公共接口后面隐藏不同的实现

在erlang中的公共接口后面隐藏不同的实现,erlang,otp,Erlang,Otp,我有一段erlang代码,它应该从一个db读取一些值,并且应该支持两个db。我希望我的代码在某种程度上不依赖于数据库,所以我实现了两个不同的gen_服务器,它们都使用同一个atom(db_处理程序)注册。我决定应该从哪个版本开始读取.app文件 两个gen_服务器公开了一个公共句柄_调用,因此我可以在应用程序的其他部分中使用以下内容: gen_server:call(db_handler, {do_something, "value1", "value2"}) 这是可行的,但它仍然与以下事实紧

我有一段erlang代码,它应该从一个db读取一些值,并且应该支持两个db。我希望我的代码在某种程度上不依赖于数据库,所以我实现了两个不同的gen_服务器,它们都使用同一个atom(db_处理程序)注册。我决定应该从哪个版本开始读取.app文件

两个gen_服务器公开了一个公共句柄_调用,因此我可以在应用程序的其他部分中使用以下内容:

gen_server:call(db_handler, {do_something, "value1", "value2"})
这是可行的,但它仍然与以下事实紧密耦合:新db的每个和任何未来实现都应该是gen_服务器

handle_call({do_something, Driver, Value1, Value2}, _From, State) ->
  Reply = Driver:do_something(Value1, Value2),
  {reply, Reply, State}.
我在考虑用这个!运算符和handle_info中的handle命令,但我仍然认为可能有更好的解决方案(可能通过另一个模块?)


有谁能告诉我在erlang中处理类似问题的更好方法吗?

每个数据库驱动程序都可以是一个库模块,用于公开gen_服务器的功能

handle_call({do_something, Driver, Value1, Value2}, _From, State) ->
  Reply = Driver:do_something(Value1, Value2),
  {reply, Reply, State}.

对于每个db服务器,添加一个通用接口来抽象调用:

-module(db_server1).

...

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

...
另一个不使用gen server

-module(db_server2).

...

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

...
创建一个新进程(gen_server:o),该进程接收用于选择数据库服务器并将其存储在其状态的参数作为init参数(例如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}.

对于非阻塞接口,使用cast或等效接口,这仍然要求每个实现都有自己的gen_server进程,对吗?不,约束是接口函数的每个实现都有相同的“契约”:相同的参数列表,相同的返回值。