2014-04-09 23 views
4

我有一段erlang代碼,它應該從db讀取一些值並應支持幾個dbs。我想我的代碼在某種程度上不依賴於數據庫,所以我實現了兩個不同的gen_servers,它們都使用相同的原子(db_handler)註冊。我決定應該從閱讀.app文件開始閱讀哪個版本。在erlang中隱藏通用接口背後的不同實現

兩個gen_servers暴露共同handle_call,所以我可以在我的應用程序像其他部分使用:

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

這工作,但仍然強烈耦合到一個事實,即每未來實現對於新的數據庫應該是gen_server。

我正在考慮使用!運算符並處理handle_info中的命令,但我仍然認爲可能有更好的解決方案(可能會通過另一個模塊?)。

有人可以給我一些更好的方式來處理erlang中這樣的事情的見解嗎?

回答

2

各個DB服務器添加的通用接口抽象的呼叫:

-module(db_server1). 

... 

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

... 

另一個沒有使用根服務器

-module(db_server2). 

... 

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

... 

創建新的進程(一個gen_server:○)它接收用作選擇db服務器並將其存儲在其狀態(例如db_server2)中的param作爲初始參數,

每個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}. 

對於非阻塞接口同樣的事情,用鑄造或等同

+0

這仍然需要每個實現有自己的gen_server進程,不過,對不對? –

+0

否,約束條件是每個接口函數的實現具有相同的「合同」:相同的參數列表,相同的返回值。 – Pascal

0

每個數據庫驅動程序都可以是一個爲gen_server公開函數的庫模塊。

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