静态工厂
Java 和 Kotlin 库中不乏这样的例子。
比如 Long.valueOf("1")
,Channel()
相较于构造器,有一些显而易见的优点:
- 不同的构造行为能够具有不同的名称
- 能抛异常
- 工厂函数可以 suspend
由于构造对象的过程完全可控,更有以下优点:
- 缓存,可以检测是否对象存在已在缓存中,从而减少资源占用
- 多态,方法返回值并没有被限制,你可以返回该类型,或该类型的子类
- 可以使用 inline reified
在 Kotlin 中编写静态工厂有几种常见的做法:
使用 companion object
class Server private constructor(url: URL) {
companion object {
fun create(ip: String, port: Int = 8080): Server =
(URL(ip = ip, port = port))
Server}
}
companion object
即为伴生对象,和之前讲的
object
一样,是和对应类绑定的单例。在使用方法和 Java
的静态方法没有区别。Server.create("localhost")
即可。
但请注意,它和 Java 的静态类型并不是一个东西。正如它的名字
object
,这会在运行时创建一个对象。如果你想真正地创建静态方法,可以使用
@JvmStatic
,但这非常不必要。
顶级函数
public fun <T> listOf(vararg elements: T): List<T> =
if (elements.size > 0) elements.asList() else emptyList()
假”构造器”
// Kotlin Stdlib...
public inline fun <T> List(
size: Int,
init: (index: Int) -> T
): List<T> = MutableList(size, init)
这种写法和命名被 Kotlin 允许。通常用来为接口提供构造入口。
抽象工厂
抽象工厂就是对子类一系列工厂的封装。
比如解析从服务器来的 JSON 字段为对应的操作。
/**
* 抽象工厂, 提供所有 Operation 的反序列化支持
*/
object AbstractFactory {
private val factorys = listOf(SetDelayOp, RefreshListOp)
private val byType = factorys.associateBy { it.type }
fun parse(json: JSON): Operation {
val type: String = json.getField<String>("type").toString()
val factory = byType[type] ?: error("No such operation type $type")
.de
factory}
}
/**
* 工厂, 要求指定对应的 type, 提供反序列化功能
*/
interface Factory<T> {
val type: String
fun deserialize(type: String): T
}
/**Operation 接口, 有具体的 type 信息
*
*/interface Operation {
val type: String
}
/**
* 瞎编的数据类
*/
data class SetDelayOp(
override val type: String,
val delay: Long,
): Operation {
// companion object 是对应类型的工厂
companion object : Factory<SetDelayOp> {
override val type: String = "VENDOR"
override deserialize(type: String): SetDelayOp {
// ...
return operation
}
}
}
// 又一个瞎编的数据类...
data class RefreshListOp(
override val type: String,
val ownerId: Long,
val listId: Long,
val listName: String,
val content: List<Text>,
): Operation {
data class Text {
val author: String,
val content: String,
}
companion object : Factory<RefreshListOp> {
override val type: String = "VENDOR"
override deserialize(type: String): RefreshListOp {
// ...
return operation
}
}
}
所以抽象工厂没什么难理解的,无非是将具体类型的一系列工厂包装起来,提供统一的返回接口。