当前位置: 首页 > news >正文

设计模式——策略模式

一 简介

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

二 策略模式

2.1 背景

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

2.2 实现设计

在这里插入图片描述

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

2.3 代码实例

定义一个算法接口

interface Discount {
    fun calculate(money:Int):Int
}

将三种优惠算法实现

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()
    }
}

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

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)


}

测试

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. 一个类拥有很多行为,而又需要使用if-else或者switch语句来选择具体行为时。使用策略模式把这些独立行为独立到具体的策略类中,可以避免多重选择的结构。
  4. Android中的应用:我们使用的ListView需要设置Adapter,而这个Adapter可以根据我们的实际需求使用SimpleAdapter、ArrayAdapter等等,这里就运用到策略模式。

优点

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

缺点

  1. 策略的增多会导致子类变化更多
  2. 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。。

相关文章:

  • “一万字”动静图生动结合详解:快速排序
  • Linux命令详解(14)useradd命令
  • 面试题之Java的异常
  • k8s helm Seata1.5.1
  • 物业公司如何解决降本增收?快鲸智慧社区系统来帮你
  • MobTech 短信验证Android端 API
  • kafka学习总结
  • 政策汇总 | 川渝发布若干政策支持双城经济圈健康发展、岷山行动计划第三批项目申报解答......近期16个政策汇总
  • Vue3.0中使用路由进行跳转和传参以及取值
  • 迷茫了3年:做完这个测试项目,我终于决定辞职
  • 时间相关模块
  • LINU下登录脚本的执行顺序
  • MySQL 文本函数和窗口函数
  • springboot+cloud实战派PDF让开发和微服务架构像喝水一样简单
  • QML自定义的日历控件
  • 分享一款快速APP功能测试工具
  • 【笔记】你不知道的JS读书笔记——Promise
  • java概述
  • Mysql优化
  • node学习系列之简单文件上传
  • npx命令介绍
  • QQ浏览器x5内核的兼容性问题
  • SpiderData 2019年2月13日 DApp数据排行榜
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • Vue2.x学习三:事件处理生命周期钩子
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 手写双向链表LinkedList的几个常用功能
  • 想写好前端,先练好内功
  • 阿里云ACE认证学习知识点梳理
  • ​DB-Engines 12月数据库排名: PostgreSQL有望获得「2020年度数据库」荣誉?
  • ​LeetCode解法汇总2583. 二叉树中的第 K 大层和
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (pytorch进阶之路)扩散概率模型
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (二)学习JVM —— 垃圾回收机制
  • (力扣记录)1448. 统计二叉树中好节点的数目
  • (四)模仿学习-完成后台管理页面查询
  • (转) Android中ViewStub组件使用
  • .NET 8 中引入新的 IHostedLifecycleService 接口 实现定时任务
  • .net core 3.0 linux,.NET Core 3.0 的新增功能
  • .NET MVC 验证码
  • .NET 反射 Reflect
  • .Net(C#)自定义WinForm控件之小结篇
  • .NET:自动将请求参数绑定到ASPX、ASHX和MVC(菜鸟必看)
  • .netcore 获取appsettings
  • .NET成年了,然后呢?
  • .NET企业级应用架构设计系列之开场白
  • .NET与 java通用的3DES加密解密方法
  • .Net中间语言BeforeFieldInit
  • .project文件
  • :=
  • @Autowired标签与 @Resource标签 的区别