借助spring更优雅地实现策略模式

436 阅读2分钟

前言

策略模式是开发中常见的一种设计模式,通常用于对不同场景需采取不同行为的场合。本文简要介绍策略模式的实现,以及一个在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的这一特性,作者是从大佬同事处得知,目前尚未找到官方文档中的相关说明。