2014-01-17 2 views
0

меня есть черта DbClientUtil, что выглядит следующим образом:Инициализация клиента базы данных в черте

trait DbClientUtil{ 
    lazy val dbClient = //Initializing client here 
} 

У меня есть объект Dbhelper, который расширяет черту DbClientUtil следующим образом:

object DbHelper extends DbClientUtil{ 
    def sendDbPayload(dbModel:DbModel):Unit = { 
     dbClient.sendData(dbModel) 
    } 
} 

В приведенном выше данный пример sendData - это метод на dbClient.

Теперь я хочу выполнить итерацию по коллекции, преобразовать элементы в модель, отправить ее в db и затем закрыть клиент.

Итак, я пишу эту стратегию в следующем объекте

object Runner extends DbClientUtil{ 
    import DbHelper._ 
    List(DbModel("model1"),DbModel("model2"),DbModel("model3")).foreach{ 
     model => sendDbPayload(model) 
    } 
    dbClient.shutdown 
} 

У меня есть два объекта, которые проходят один и тот же признак. DBHelper и Runner имеют такую ​​же черту DbClientUtil. DbClientUtil инициализирует dbClient. Инициализированный dbClient используется как DbHelper, так и Runner. Мой вопрос: два раза я инициализирую dbClient? Мой следующий вопрос был бы, если бы я инициализировал его дважды, что было бы лучшим способом переписать это, чтобы предотвратить любые избыточные инициализации?

Thanks

ответ

2

На самом деле да. DbClientUtil инициализирует дважды: сначала DbHelper, а затем Runner. Если это проблема, есть много способов решить эту проблему:

1) сделать DbClientUtil без гражданства и переписать его как def dbClient. Это на самом деле хорошее решение, потому что ваше состояние должно храниться в базе данных, независимо от количества созданных вами клиентов.

2) создать singleton. Только один. Не два:

object DbClientUtil extends DbClientUtil 

object DbHelper extends DbClientUtil{ 
    def sendDbPayload(dbModel:DbModel):Unit = { 
    DbClientUtil.sendData(dbModel) 
    } 
} 

object Runner { 
     List(DbModel("model1"),DbModel("model2"),DbModel("model3")).foreach{ 
    model => DbHelper.sendDbPayload(model) 
    } 
    DbHelper.shutdown //Use just one client, not two 
} 

Но на самом деле мне это не нравится. Строгие зависимости дают больше сцепления

3) Используйте инъекцию зависимости. Я думаю, это лучшее решение для крупных проектов. Например, вы можете использовать Google Guice:

trait DbClientService { 
    def sendData(data: Any): Unit //No implementation 
} 

class DbClientServiceImpl extends DbClientService 
    def sendData(data: Any): Unit { 
     //write you implementation code 
    } 
} 

Bind него: https://github.com/codingwell/scala-guice/

class ServiceModule extends AbstractModule { 
    protected def configure() { 
    bind[DbClientService].to[DbClientServiceImpl].in[Singleton] 
    } 
} 

А затем вводят его:

class DbHelper @Inject()(dbClient:DbClientService) extends DbClientUtil{ 
    def sendDbPayload(dbModel:DbModel):Unit = { 
    dbClient.sendData(dbModel) 
    } 
} 

class Runner @Inject()(dbClient:DbClientService) extends DbClientUtil{ 

    List(DbModel("model1"),DbModel("model2"),DbModel("model3")).foreach{ 
    model => dbClient.sendDbPayload(model) 
    } 
    dbClient.shutdown 
    //still, don't know if it is good solution 
    //to control client state from outer scope 
    //better make this logic private 
} 
Смежные вопросы