我正在尝试创建一个用于测试Room迁移的模板类。测试Room迁移应该遵循的步骤如下:
- 在以前的版本中创建数据库。
- 用户迁移帮助器迁移到下一个版本。
- 验证数据的完整性。
现在我已经创建了一个类MigrationHelper,它实现了所有这些方法。
class MigrationHelper {
fun createDatabase(version : Int) : MigrationHelper{
initialDatabase = migrationTestHelper.createDatabase(TEST_DB_NAME , version)
return this
}
fun insertData(db : SupportSQLiteDatabase){
...
}
}
现在对于这个类,我目前使用builder方法,以便编写测试的开发人员可以以一种干净易懂的方式调用方法。
@Test
fun runMigration_78_79(){
migrationHelper.setUp("test_db")
.addTablesInvolved("packs")
.createDatabaseWithData(78)
.addMigrations(MIGRATION_77_78,MIGRATION_78_79)
.runMigration(79)
.cleanOut()
}
但是自从构建器模式以来,任何方法都可以以任何顺序调用。这对我的实现来说并不好,因为有些方法必须按顺序调用。例如:可以在'addMigration'方法之前调用'runMigration'方法,因为要运行迁移,您需要添加所涉及的所有迁移的数组。
对于这种情况,最好的设计模式是什么?我知道我可能过于复杂了,我可以用一堆方法创建一个类,然后单独调用它们。但我想要一个干净利落的方法。谢谢你。当您将所有内容放入一个构建器中时,构建器模式本身并没有帮助,但是您可以将方法拆分为反映当前状态的不同构建器。当每个构造器仅由只能在相应状态下执行的操作组成时,就不可能以错误的顺序调用操作。
例如,您可以有一个InitialBuilder
,它有一个函数setUp
,返回一个EmptyDbBuilder
,然后可能包含一个函数addTablesInvolved
,返回一个DbWithTablesBuilder
,等等。
这样,您就可以完全控制在不同情况下可以或不可以调用的函数。
你的"builder模式"Example并不是真正的构建器模式。它只是使用链式方法调用,而不构建任何东西。
构建器模式实际上允许您以任何顺序提交调用,因为方法调用只收集参数,然后有一个最后的方法调用来执行整个集合。最后的方法调用将以正确的顺序执行工作。就像下面这样。这只是一个示例——我没有做过这样的房间测试,所以我的一些语法可能在那部分是错误的。
class MigrationHelper private constructor(val databaseName: String) {
companion object {
fun build(databaseName: String) = MigrationHelper(databaseName)
}
private var startingDatabaseVersion: Int? = null
private val tables = mutableSetOf<String>()
private val migrations = mutableSetOf<Migration>()
private val migrationsToRun = mutableSetOf<Int>()
fun createDatabase(version : Int): MigrationHelper {
startingDatabaseVersion = version
return this
}
fun addTablesInvolved(vararg tables: String): MigrationHelper {
for (table in tables) this.tables += table
return this
}
fun addMigrations(vararg migrations: Migration): MigrationHelper {
for (migration in migrations) this.migrations += migration
return this
}
fun runMigration(version: Int): MigrationHelper {
migrationsToRun += version
return this
}
fun execute() {
val startingVersion = startingDatabaseVersion ?:
error("Missing initial version. Must call createDatabaseWithData() before execute()")
migrationTestHelper.createDatabase(databaseName, startingVersion)
.addMigrations(*migrations.toTypedArray())
.build()
.use {
for (table in tables) {
// add table to db
}
for (migration in migrationsToRun.sorted()) {
// run migration
}
}
}
}
用法:
MigrationHelper.build("test_db")
.addTablesInvolved("packs")
.createDatabaseWithData(78)
.addMigrations(MIGRATION_77_78,MIGRATION_78_79)
.runMigration(79)
.execute()
// Everything between the first and last lines above can be entered in any order.