用于创建具有多个方法的类的设计模式,这些方法应该按顺序执行



我正在尝试创建一个用于测试Room迁移的模板类。测试Room迁移应该遵循的步骤如下:

  1. 在以前的版本中创建数据库。
  2. 用户迁移帮助器迁移到下一个版本。
  3. 验证数据的完整性。

现在我已经创建了一个类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.

相关内容

  • 没有找到相关文章

最新更新