本文原始发表于:https://juejin.cn/post/6955740450061811720
使用场景
考虑这样一种场景:我们是一个汽车生产商,我们生产各种品牌的汽车,比如宝马、奔驰、奥迪等等,为了面向对象开发,我们定义一个基类 Car
abstract class Car {
fun brand(): String // 每辆车都有一个品牌
}
各个牌子的车
class BMW : Car {
override fun brand(): String {
return "BMW"
}
}
class Benz : Car {
override fun brand(): String {
return "Benz"
}
}
class Audi : Car {
override fun brand(): String {
return "Audi"
}
}
我们是汽车生产商,我们生产车,而不是搬运工,我们需要一个生产车间,因此我们需要定义一个工厂类 CardFactory
class CardFactory {
fun produceCar(brand: String): Car {
when (brand) {
"BMW" -> return BMW()
"Benz" -> return Benz()
"Audi" -> return Audi()
}
}
}
看起来非常完美,使用了工厂模式,很高级,需要生产什么牌子的车,直接传一个品牌名字就可以生产出对应牌子的汽车了。我们把这一套生产流程交给公司的骨干 小明 负责。
随着我们的生意越做越大,我们生产的汽车品牌越来越多,但是没有关系,得益于我们良好的封装,我们只需要继承 Car
类,实现新品牌汽车,然后在工厂类 CardFactory
中增加一个 when -> case 的判断就好了,由于小明非常熟悉这一套生产流水线,所以每一次有新增品牌都难不倒小明。
后来公司越做越大,小明从基础骨干晋升为部门 Leader,为了提高工作效率,汽车品牌的实现交给 小白 负责,工厂的负责人分配给了 小黑 ,由于小白只负责汽车的实现,小黑只负责工厂的管理,所以常常出现一个问题:小白实现了一个新品牌汽车,而小黑没有在工厂中新增新品牌汽车的生产逻辑,这就导致生产线出现了问题
为了解决这个问题,小明想到了一个方法:其实每次有新增品牌的汽车,工厂类只需要增加一个判断逻辑即可,工作十分枯燥,甚至有点冗余。这里有一个可优化的点,只要 Car 的实现类确定之后,工厂类的新增代码就是固定的,即模板代码是确定的。于是小明发明了一套基于 Annotation Processor
和编译时注解实现的自动生成工厂类代码的方案
首先自定义一个注解类 @CarAnnotation
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
annotation class CarAnnotation(val brand: String)
然后在各个子类中加上这个注解
@CarAnnotation("BMW")
class BMW : Car {
override fun brand(): String