5分钟规划方式之战略方式(Strategy Pattern)

规划方式是软件开发中的常用方式,但是实践上许多人仅仅了解其概念,而在实践开发中并不知道怎么运用。因而,咱们能够结合实践开发事例来详细解说战略方式。

假如您有任何疑问、对文章写的不满意、发现错误或许有更好的办法,欢迎在谈论、私信或邮件中提出,十分感谢您的支撑。

1、收到需求

假设咱们需求自界说的 View 类,它需求完成不同的动画作用,包括平移、旋转、缩放等等等等。咱们能够运用战略方式来完成这个功用,使得每种动画作用都对应一个战略类。

2、不运用战略方式

需求在 AnimatedView 类中完成所有的动画作用

class AnimatedView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
    var animationType: String = "translate"
    fun startAnimation() {
        when (animationType) {
            "translate" -> {
                // 完成平移动画
            }
            "rotate" -> {
                // 完成旋转动画
            }
            "scale" -> {
                // 完成缩放动画
            }
            else -> {
                throw IllegalArgumentException("Invalid animation type")
            }
        }
        invalidate()
    }
}

调用如下,需求在 AnimatedView 目标中设置动画类型,然后调用 startAnimation 办法来开端动画:

animatedView.apply {
    animationType = "translate"
}.startAnimation()
animatedView().apply {
    animationType = "rotate"
}.startAnimation()

在这种完成办法中,假如需求添加或修正动画作用,咱们需求修正 AnimatedView 类中的代码,这样会添加代码的复杂度和保护本钱。

3、运用战略方式

而运用战略方式,咱们只需求添加或修正战略完成类即可,而不需求修正现有的代码。因而,运用战略方式能够更好地完成代码的可扩展性和可保护性。

咱们将动画有多种完成办法(不同的行为)这些行为当作一个AnimationStrategy 战略接口

界说了一个运用动画的战略

interface AnimationStrategy {
    fun applyAnimation(view: View)
}

它仅仅一个接口,等候详细的动画完成 ,而刚开端的经过设置animationType,在onDraw中经过if来判别的办法

修正为了运用当前的战略目标

private var animationStrategy: AnimationStrategy? = null

在onDraw中调用

override fun onDraw(canvas: Canvas?) {
    super.onDraw(canvas)
    if (animationStrategy != null) {
        animationStrategy!!.applyAnimation(this)
    }
}

咱们再随意写几个界说不同的战略完成类,这些完成类完成了 AnimationStrategy 接口,并且依据不同的需求,能够挑选不同的战略完成类来运用不同的动画作用。

class TranslateAnimationStrategy : AnimationStrategy {
    override fun applyAnimation(view: View) {
        // 完成平移动画
    }
}
class RotateAnimationStrategy : AnimationStrategy {
    override fun applyAnimation(view: View) {
        // 完成旋转动画
    }
}
class ScaleAnimationStrategy : AnimationStrategy {
    override fun applyAnimation(view: View) {
        // 完成缩放动画
    }
}

运用办法如下,依据不同的需求来挑选不同的战略完成类

animatedView.apply {
    animationStrategy = TranslateAnimationStrategy() // 履行平移动画
    //or
    animationStrategy = RotateAnimationStrategy() // 履行旋转动画
    //or
    animationStrategy = ScaleAnimationStrategy()// 履行缩放动画
}

AnimationStrategy 接口作为一个一致的接口,能够使得不同的战略完成类能够被一致地运用,然后完成了代码的解耦和可扩展性。

整合起来

class AnimatedView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
    var animationStrategy: AnimationStrategy? = null
        set(value) {
            field = value
            invalidate()
        }
    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        animationStrategy?.applyAnimation(this)
    }
}

4、总结

战略方式是一种行为型规划方式,它允许在运行时动态地挑选算法或行为,然后使得算法或行为能够独立于运用它们的客户端而变化。在比如中动画的改变,并不需求修正AnimatedView

通常由一个接口或抽象类和多个完成类组成。客户端经过调用接口或抽象类中的办法来履行算法或行为,而详细的完成则由战略完成类来完成。在比如中AnimationStrategy为接口,各个动画为完成类。AnimatedView经过animationStrategy?.applyAnimation(this)来履行

如此咱们也能够看出

  1. 一个类需求在运行时依据不同的状况选用不同的算法或行为。
  2. 一个类界说了许多行为,并且这些行为在类的办法中以多个条件句子的方式出现,将这些行为“分化”到不同的战略类中,能够防止条件句子的复杂度。
  3. 算法的运用频率不高,能够把它们封装到战略类中,然后防止让整个体系变得臃肿。
  4. 多个类只有在算法或行为上稍有不同的状况。

运用战略方式能够添加代码的灵活性和可保护性,使得代码更易于扩展和修正。不过可不要乱用,究竟多了许多个类,不是嘛。

5、结束

规划方式是一个十分广泛的论题,许多规划方式又有极高的类似度,刚接触很容易混淆,因而很难知道在什么状况下应该运用哪种规划方式。我将极力提供在开发过程中遇到的最小单元的规划方式事例。更好地了解何时以及怎么运用规划方式。

假如您有任何疑问、对文章写的不满意、发现错误或许有更好的办法,欢迎在谈论、私信或邮件中提出,十分感谢您的支撑。

那么下篇见

“开启成长之旅!这是我参加「日新计划 2 月更文挑战」的第 4 天,点击检查活动概况”