前言
策略模式是开发中常见的一种设计模式,通常用于对不同场景需采取不同行为的场合。本文简要介绍策略模式的实现,以及一个在spring中实现策略模式时可以借助的便利特性,代码使用kotlin编写。
需求场景
设想需实现如下业务场景:实现一个迎宾机器人,针对来客的不同身份给出不同的问候语。
简单实现
一个简单实现可能是这样的:
class GreetingService {
fun greet(identity: String) {
when(identity) {
"lover" ->
println("亲爱的,你来啦,mua~")
"elder" ->
println("您来啦,里边请,请上座~")
"closeFriend" ->
println("哎哟~,这是哪阵风把您给吹来了")
else ->
println("你谁呀你,哪凉快哪呆着去吧")
}
}
}
这种方式处理简单业务是完全够用的,但在分支较多、每个分支流程较长时,可能会造成这个函数甚至整个代码文件体积膨胀,这时就需要使用策略模式对代码进行重新设计。
使用策略模式重构
使用策略模式重构的GreetingService可能是这样的:
interface GreetingService {
fun greet()
}
class LoverGreetingServiceImpl : GreetingService {
override fun greet() {
println("亲爱的,你来啦,mua~")
}
}
class ElderGreetingServiceImpl : GreetingService {
override fun greet() {
println("您来啦,里边请,请上座~")
}
}
class CloseFriendGreetingServiceImpl : GreetingService {
override fun greet() {
println("哎哟~,这是哪阵风把您给吹来了")
}
}
object StrangerGreetingServiceImpl : GreetingService {
override fun greet() {
println("你谁呀你,哪凉快哪呆着去吧")
}
}
private val greetingServices: Map<String, GreetingService> = mapOf(
Pair("lover", LoverGreetingServiceImpl()),
Pair("elder", ElderGreetingServiceImpl()),
Pair("closeFriend", CloseFriendGreetingServiceImpl())
)
fun greet(identity: String) {
greetingServices[identity]?.greet() ?: StrangerGreetingServiceImpl.greet()
}
可以看到,虽然代码规模有所增加,但我们实现了问候服务定义和实现的分离。可以预见,在处理较大规模问题,这种处理方式更容易扩展和维护,也可以方便地对每种实现进行测试。
在spring中使用
若是使用spring时需要使用策略模式,spring提供了一个非常优雅的特性:只需将服务实现标记为Bean(例如使用@Service),给出Bean的名称,spring就会在Map<String, Service>这样的成员中帮我们完成Bean创建和注入。
@RestController
class GreetingController(
@Resource
val greetingServices: Map<String, GreetingService>
) {
private val logger = LoggerFactory.getLogger(GreetingController::class.java)
@GetMapping("/v1/greeting/{identity}")
fun greet(
@PathVariable("identity")
identity: String) {
logger.info("greet, identity=$identity")
greetingServices[identity]?.greet() ?: StrangerGreetingServiceImpl.greet()
}
}
// 其它实现同理
@Service("lover")
class LoverGreetingServiceImpl : GreetingService {
override fun greet() {
println("亲爱的,你来啦,mua~")
}
}
总结
本文简单实现了策略模式,并借助spring的特性使其更加优雅。关于spring的这一特性,作者是从大佬同事处得知,目前尚未找到官方文档中的相关说明。