scala pattern
最近,Debasish Ghosh也发表了类似主题的博客 。 我认为他的文章是对该主题的很好的介绍。
以下是我在蛋糕图案方面遇到的一些问题。 (高阶功能将在下篇文章中介绍。)如果您对任何一个功能都有解决方案,请告诉我!
使用组件实现参数化系统
首先,无法对具有组件实现的系统进行参数化。 假设我具有三个组件:带有实现的DatabaseComponent,UserRepositoryComponent,UserAuthenticatorComponent,将按以下方式创建系统的顶级环境/入口点:
val env = new MysqlDatabaseComponentImpl
with UserRepositoryComponent
with UserAuthenticatorComponent
现在要创建一个具有模拟数据库的测试环境,我将必须做:
val env = new MockDatabaseComponentImpl
with UserRepositoryComponent
with UserAuthenticatorComponent
注意多少代码是相同的。 这不是3个组件的问题,但是如果有20个呢? 为了改变一个组件的实现,除了一个组件外,所有其他组件都必须重复。 显然,这会导致很多代码重复。
组件配置
通常需要配置组件。 假设我有一个UserAuthenticatorComponent,它依赖于UserRepositoryComponent。 但是,身份验证器组件具有抽象的val encryptionMethod,用于配置加密算法。 如何配置组件? 有两种方法。 定义环境时,抽象值可以具体化,例如:
val env = new MysqlDatabaseComponentImpl
with UserRepositoryComponent
with UserAuthenticatorComponent {
val encryptionMethod = EncryptionMethods.MD5
}
但是,如果我想重用已配置的组件怎么办? 一个明显的答案是扩展UserAuthenticatorComponent特性。 但是,如果该组件具有任何依赖项(在蛋糕模式中使用自类型表示),则必须重复它们,因为不继承自类型。 因此,可重用的,已配置的组件可能如下所示:
trait UserAuthenticatorComponentWithMD5
extends UserAuthenticatorComponent {
// dependency specification duplication!
this: UserRepositoryComponent =>
val encryptionMethod = EncryptionMethods.MD5
}
如果我们不重复自类型,则编译器将抱怨UserAuthenticatorComponent使用不正确。
无法控制初始化顺序
与配置有关的一个问题是,没有一种类型安全的方法来确保以正确的顺序初始化组件。 如上所述,假设UserAuthenticatorComponent具有抽象的encryptionMethod,在创建组件时必须指定该方法。 如果我们还有另一个依赖UserAuthenticatorComponent的组件:
trait PasswordEncoderComponent {
this: UserAuthenticatorComponent =>
// encryptionMethod comes from UserAuthenticatorComponent
val encryptionAlgorithm = Encryption.getAlgorithm(encryptionMethod)
}
并如下初始化我们的系统:
val env = new MysqlDatabaseComponentImpl
with UserRepositoryComponent
with UserAuthenticatorComponent
with PasswordEncoderComponent {
val encryptionMethod = EncryptionMethods.MD5
}
那么在初始化cryptoAlgorithm时,encryptionMethod将为null! 防止这种情况的唯一方法是在PasswordEncoderComponent之前混入UserAuthenticatorComponentWithMD5。 但是类型检查器不会告诉我们。
优点
不要误会我不喜欢蛋糕模式–我认为它提供了一种很好的方式来构建程序。 例如,它消除了对工厂的需求( 我不是非常喜欢的工厂),或者很好地分离了对组件的依赖和对数据的依赖(*)。 但是,它可能会更好;)。
(*)在这里,每个代码片段实际上都有两种类型的参数:普通方法参数(可用于传递数据)和组件参数(表示为包含组件的自身类型)。 是否应区别对待这两种类型的参数是一个很好的问题:)。
您在Scala中使用DI有哪些经验? 您是否使用Java DI框架,上面使用的方法之一或其他方法?
参考: Scala中的DI: Adam Warski 博客上我们JCG合作伙伴 Adam Warski的 Cake Pattern优缺点 。
翻译自: https://www.javacodegeeks.com/2011/10/di-in-scala-cake-pattern-pros-cons.html
scala pattern