• 设计模式——策略模式


    一 简介

    通过选择策略类,来执行不同算法分支。核心是通过注入对象,改变行为。

    策略模式

    2.1 背景

    Jack的水果店新增加优惠卷活动,所以整个程序流程在结算的时候又多了扣去优惠,并且优惠服务是可选择的。

    2.2 实现设计

    在这里插入图片描述

    • 1、将每一种优惠策略,单独成一个独立对象,独立出来。
    • 2、使用方法通过选择不同的组件,达到不同的行为

    2.3 代码实例

    定义一个算法接口

    interface Discount {
        fun calculate(money:Int):Int
    }
    
    • 1
    • 2
    • 3

    将三种优惠算法实现

    class FullDiscount:Discount {
        override fun calculate(money: Int): Int {
            if (money>200){
                println("优惠减免20元")
                return money-20
            }
            return money
        }
    }
    
    
    class NewerDiscount:Discount {
        override fun calculate(money: Int): Int {
            println("新顾客尊享满100减20")
            if (money>100){
                return money-20
            }
            return money
        }
    }
    
    
    class SecondDiscount:Discount {
        override fun calculate(money: Int): Int {
            val balance = money*0.9
            return balance.toInt()
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    使用策略模式注入不同的算法

    abstract class ShoppingCart(open var products:List<Fruit> = ArrayList()) {
        private var discount:Discount?=null
    
        @JvmName("setDiscount1")
        fun setDiscount(discount: Discount){
            this.discount =discount
        }
    
        //提交订单
        fun submitOrder(){
            //计算商品金额
            var money = balance()
            money = discount!!.calculate(money)
            println("需要支付的总金额为${money}元")
            //保存订单
            pay(money)
            //送货上门
            sendHome()
        }
        //计算金额
        private fun balance():Int{
            var money:Int = 0
            println("商品清单:")
            for (fruit in products){
                Factory.pack(fruit,fruit.price)
                println("${fruit.name},${fruit.price}")
                money+=fruit.price
            }
    
            return money
        }
    
        private fun sendHome(){
            println("三公里以内,免费送货上门")
        }
    
        //提交保存
        abstract fun pay(money:Int)
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    测试

    class ShoppingCartClient {
        companion object{
            var discounts:MutableMap<String,Discount> = mutableMapOf()
            init {
                discounts["full"] = FullDiscount()
                discounts["newer"] = NewerDiscount()
                discounts["second"] = SecondDiscount()
            }
            @JvmStatic
            fun main(args: Array<String>) {
                val banana = Banana("香蕉",40)
                val apple = Apple("苹果",50)
                val banana2 = Banana("黄金蕉",60)
                val shopping = OnlineShopping(listOf(banana,apple,banana2))
                discounts["newer"]?.let { shopping.setDiscount(it) }
    
                shopping.submitOrder()
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    测试结果
    在这里插入图片描述

    三 应用场景

    1. 同一个问题具有不同算法时,即仅仅是具体的实现细节不同时。
    2. 对用户隐藏具体策略的实现细节,彼此完全独立;提高算法的保密性与安全性。
    3. 一个类拥有很多行为,而又需要使用if-else或者switch语句来选择具体行为时。使用策略模式把这些独立行为独立到具体的策略类中,可以避免多重选择的结构。
    4. Android中的应用:我们使用的ListView需要设置Adapter,而这个Adapter可以根据我们的实际需求使用SimpleAdapter、ArrayAdapter等等,这里就运用到策略模式。
    5. java jdk里面的Arrays工具类,我们可以根据重写Compartor接口里的compare方法,里进行排序策略的改变

    优点

    1. 策略类可以互相替换,由于策略类都实现同一个接口,因此他们能够互相替换。
    2. 耦合度低,方便扩展,增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合开闭原则。
    3. 避免使用多重条件选择语句(if-else或者switch)。

    缺点

    1. 策略的增多会导致子类变化更多
    2. 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。。
  • 相关阅读:
    增强LLM:使用搜索引擎缓解大模型幻觉问题
    【Rust日报】2022-08-02 hypher 将30种自然语言塞到1.1M空间内
    MySQL字符集设置、密码管理
    dji uav建图导航系列()move_base
    Visual Studio 2019 2022 创建 Visual Studio 2013中的的Win32项目
    【java技术路线】1.1 java语言环境与基本数据类型
    【Java】医院智能导诊系统源码:解决患者盲目就诊问题、降低患者挂错号比例
    Jupyter的安装
    MySql数据库-SQL函数
    打工人,这里有一份述职技巧,请查收
  • 原文地址:https://blog.csdn.net/qq_39431405/article/details/126623681