Android設(shè)計模式(四) 策略模式

策略模式用于算法的自由切換和擴展,分離算法的定義與實現(xiàn)。

  • 好處:將不同的行為策略(Strategy)進行獨立封裝,與類在邏輯上解耦,即可以動態(tài)改變對象的行為
  • 原則:抽取代碼中變化的部分來實現(xiàn)一個接口,并提供多種實現(xiàn)類,即算法。調(diào)用方需要使用這個接口的時候,可以動態(tài)的選擇這些實現(xiàn)類。算法的變化獨立于使用算法的調(diào)用者,從而可以輕松的擴展與改變策略,實現(xiàn)對象的動態(tài)改變行為,符合OCP原則

Android中策略模式的應(yīng)用有WebView設(shè)計,Animation中的Interpolator設(shè)計.....

例如電商應(yīng)用中的商品價格計算

fun main(args: Array<String>) {
    val price   = 4500.0
    val mContext = PriceStrategyContext(NormalPriceStrategy())
    mContext.strategyMethod(price)
    mContext.setStrategy(GoldPriceStrategy())
    mContext.strategyMethod(price)
}


interface PriceStrategy {
    /**
     * 計價方法
     */
    fun calculate(price: Double): Double
}

class NormalPriceStrategy : PriceStrategy {
    override fun calculate(price: Double): Double {
        println("普通用戶的計價策略方法被訪問")
        return  price
    }
}

class GoldPriceStrategy : PriceStrategy {
    override fun calculate(price: Double): Double {
        println("黃金會員的計價策略方法被訪問")
        return 0.95 * price
    }
}

class DiamondPriceStrategy : PriceStrategy {
    override fun calculate(price: Double): Double {
        println("鉆石會員的計價策略方法被訪問")
        return 0.9 * price
    }
}


/**
 * 上下文環(huán)境,定義了 PriceStrategy 接口引用,在創(chuàng)建 PriceStrategyContext 實例時傳入具體的策略類,
 * 具體策略類調(diào)用策略方法??蛻舳藙?chuàng)建 PriceStrategyContext 對象負責(zé)調(diào)用策略方法。
 */
class PriceStrategyContext() {
    private var mPriceStrategy: PriceStrategy? = null

    constructor(mPriceStrategy: PriceStrategy) : this() {
        this.mPriceStrategy = mPriceStrategy
    }

    fun setStrategy(strategy: PriceStrategy?): PriceStrategyContext {
        mPriceStrategy = strategy!!
        return this
    }

    //持有算法方法
    fun strategyMethod(price: Double) {
        mPriceStrategy!!.calculate(price)
    }
}

策略模式中的上下文環(huán)境 PriceStrategyContext 的職責(zé)是隔離客戶端與策略類的耦合,無須關(guān)注具體的策略行為。上面示例中, PriceStrategyContext 的作用只是負責(zé)調(diào)度策略類的執(zhí)行并獲取結(jié)果,并沒有完全起到隔離客戶端與策略類的作用。

通過簡單工廠模式將具體策略對象的創(chuàng)建與調(diào)用方進行隔離,也可通過策略枚舉或者策略類的配置注入,將PriceStrategyContext中的具體策略類融合在一起,簡化代碼。

簡單工廠

abstract class PriceStrategyFactory {
    companion object {
        inline operator fun <reified T : PriceStrategy> invoke(): PriceStrategy? {
            var strategy: PriceStrategy? = null
            try {
                strategy = T::class.java.newInstance() as PriceStrategy
            } catch (e: Exception) {
                e.printStackTrace()
            }
            return strategy
        }
    }
}

枚舉

fun main(args: Array<String>) {
    PriceStrategy.GOLD.calculate(4500.0)
}

enum class PriceStrategy(var type: String) {
    //
    NORMAL("normal") {
        override fun calculate(price: Double): Double {
            println("普通用戶的計價策略方法被訪問")
            return price
        }
    },
    GOLD("gold") {
        override fun calculate(price: Double): Double {
            println("黃金會員的計價策略方法被訪問")
            return price * 0.95
        }
    },
    DIAMOND("diamond") {
        override fun calculate(price: Double): Double {
            println("鉆石會員的計價策略方法被訪問")
            return price * 0.9
        }
    };
    
    fun setType(type: String): PriceStrategy {
        this.type = type
        return this
    }

    abstract fun calculate(price: Double): Double

    }

高階函數(shù)抽象算法

策略類僅僅是針對算法行為的一種抽象,Kotlin 中可以使用高階函數(shù)替代。

fun main(args: Array<String>) {
    PriceStrategyContext(4500.0, NormalPriceStrategy).calculate()
}

// 策略用val聲明成lambda表達式
val NormalPriceStrategy = { price: Double -> price }
val GoldPriceStrategy = { price: Double -> price * 0.95 }
val DiamondPriceStrategy = { price: Double -> price * 0.9 }

class PriceStrategyContext(private val price: Double, private val priceStrategy: (Double) -> Double) {
    // 
    fun calculate() = priceStrategy(price)
}

策略模式需要不停的在各個算法間切換,造成很多邏輯判斷,我們可以配合使用一些其他的模式去消除。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容