2011-04-12 104 views
4

让我的应用程序包含业务类Order,Product,Customer等,我想在数据库中存储/检索它们。斯卡拉DAO与类型分类

通常,我们使用DAO模式来达到此目的。也就是说,我们定义了一个DAO接口和实现为每一个企业类:OrderDAOProductDAO等。现在我想用型类模式:

trait DAO[T] { 
    def create(t:T) 
    ... // other CRUD operations 
} 
... 
// DAO implementations for specific business objects 
implicit object OrderDAO extends DAO[Order] { 
    def create(o:Order) {...} 
    ... // other CRUD operations 
} 
... 
// create a business object in the database 
def create[T](t:T)(implicit dao:DAO[T]) {dao.create(t)}

现在我的问题是,所有DAOs使用DataSource实例(数据库连接的工厂),因此我无法将DAOs定义为objects。我应该创建一个DataSource的单例实例,并在初始化时将它传递给所有DAOs

比方说,我们有一个函数来创建一个DataSource

def dataSource():DataSource = {...}
你将如何实现 DAOs类型类

回答

1

同意萨莎。电梯的方式应该工作:

trait DataSource 

class MyDataSource extends DataSource 

object DataSources { 
    @volatile var dataSource:() => DataSource =() => new MyDataSource 
} 

有了这样的方法,你可以使用object没有松动的可测试性。

+0

有趣。你能解释一下吗? – Michael 2011-04-12 18:15:24

+0

对不起,代码有误。它必须是var,而不是def,我编辑它。 – tonek 2011-04-12 19:21:48

+0

使用这种方法,您实际上在DataSources变量中定义了变量,该变量包含数据源的函数工厂。在生产代码中,您可以使用在对象DataSources中定义的变量的默认值。但在测试中,您可以重新定义该变量以返回您想要的任何内容。 – tonek 2011-04-12 19:29:12

2

我不认为类型班是去这里的路。类型类用于描述功能,而不是DI的替代品。

例如,如果您的DAO写入键值存储区,则可能需要将类转换为键和值的映射的功能。

在这种情况下,类型类:

trait KeyValuable[T] { 
    def toMap(t: T): Map[String, String] 
} 

你还可以用正确的实现提供每个业务类,无论环境的很明显。它是这种类型的继承能力,与你如何使用它无关。