Scala 关于蛋糕图案的问题

Scala 关于蛋糕图案的问题,scala,dependency-injection,dao,Scala,Dependency Injection,Dao,让几个单独的DAO类OrderDAO、ProductDAO和CustomerDAO存储/检索数据库中的数据,并共享一个实例DataSource(数据库连接工厂) 为了创建DataSource实例并将其插入DAOs中,我们通常使用springdi。现在我想在Scala中不使用任何DI框架来实现这一点 我已经读到了关于的,看起来我应该做以下事情: trait DatabaseContext { val dataSource:Datasource } trait OrderDAO {this:Dat

让几个单独的DAO类
OrderDAO
ProductDAO
CustomerDAO
存储/检索数据库中的数据,并共享一个实例
DataSource
(数据库连接工厂)

为了创建
DataSource
实例并将其插入
DAOs
中,我们通常使用springdi。现在我想在Scala中不使用任何DI框架来实现这一点

我已经读到了关于的,看起来我应该做以下事情:

trait DatabaseContext { val dataSource:Datasource }

trait OrderDAO {this:DatabaseContext =>
  ... // use dataSource of DatabaseContext
}

trait ProductDAO {this:DatabaseContext => 
  ... // use dataSource of DatabaseContext
}

object DAOImpl extends OrderDAO with ProductDAO with DatabaseContext {
  val dataSource = ... // init the data source
}
我是否正确理解蛋糕图案

我是否可以使用cake模式以不同的方式实现这些
DAO

它提供了哪些像Spring这样的DI框架没有的功能

如何创建单独的
OrderDAOImpl
ProductDAOImpl
对象来共享相同的
DataSource
实例,而不是一个大的
DAOImpl

可能:

  • 在编译时进行静态检查

蛋糕模式的优点是:

  • 与基于配置文件的DI解决方案不同,将合同与 实现在编译时完成,这减少了类查找 以及兼容性问题。然而,许多DI引擎都有一个 代码配置特性中的替代项
  • 没有第三方库 都用过了。允许您使用模式的自类型注释是 母语特征。没有使用特殊语法来检索 合同的执行
  • 忘记指定一个 另一个组件所需的组件的实现会导致 运行时错误-请查看本文 并尝试不指定其中一个组件或指定 trait,而不是任何蛋糕模式中的具体类 示例,甚至忘记初始化与所需组件对应的val
然而,为了体验这些优势,您需要更严格地遵守模式的体系结构——检查同一篇文章,并注意包含实际契约和实现的包装特性

你的例子似乎不是严格意义上的蛋糕模式。在您的例子中,您可以使用继承为您的trait创建实现,并为每个DAO组件使用单独的类。在cake模式中,消费代码将是一个组件,就像DAO代码一样,将依赖项组装在一起的代码将独立于它

为了说明蛋糕模式,您必须将消费类(域层或UI层)添加到示例中。或者,如果您的DAO组件访问彼此的特性,您可以单独在DAO上演示蛋糕模式

简而言之

trait OrderDAOComponent {
    val dao: OrderDAO
    trait OrderDAO {  
        def create: Order
        def delete(id: Int): Unit  
        //etc 
    }  
}

trait OrderDAOComponentImpl extends OrderDAOComponent {  
    class OrderDAOJDBCImpl extends OrderDAO {  
        def create: Order = {/*JDBC-related code here*/}
        def delete(id: Int) {/*JDBC-related code here*/}
        //etc
    }  
}  

//This one has a dependency
trait OrderWebUIComponentImpl {  
    this: OrderDAOComponent =>  
    class OrderWebUI {  
        def ajaxDelete(request:HttpRequest) = {  
            val id = request.params("id").toInt
            try {
                dao.delete(id)
                200
            }
            catch {
                case _ => 500
            }

        }  
    }  
}  

//This matches contracts to implementations

object ComponentRegistry extends  
    OrderDAOComponentImpl with  
    OrderWebUIComponentImpl
{  
    val dao = new OrderDAOJDBCImpl
    val ui = new OrderWebUI
}  

//from some front-end code
val status = ComponentRegistry.ui.ajaxDelete(request)
更多关于你的例子。我认为如果:

trait DatabaseContext { val dataSource:Datasource }

trait OrderDAOComponent {this:DatabaseContext =>
    trait OrderDAOImpl {
        ... // use dataSource of DatabaseContext
    }
}

trait ProductDAOComponent {this:DatabaseContext => 
    trait ProductDAOImpl {
        ... // use dataSource of DatabaseContext
    }
}

object Registry extends OrderDAOComponent with ProductDAOComponent with DatabaseContextImpl {
    val dataSource = new DatasourceImpl //if Datasource is a custom trait, otherwise wrapping needed
    val orderDAO = new OrderDAOImpl
    val productDAO = new ProductDAOImpl
}

//now you may use them separately
Registry.orderDAO.//

我只是简单地读了一下蛋糕的图案,但也没有看到令人兴奋的是什么。它似乎比现有的DI容器复杂得多,你是否喜欢它与这个问题并不相关。“我是否遗漏了什么”是一个很弱的问题。也许最好问“这提供了什么X没有?”这是一个明确的问题。@Daniel。谢谢我已重新措辞了这个问题。