记录--卸下if-else 侠的皮衣!- 策略模式
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
当我是if-else侠的时候
怕出错
给我一个功能,我总是要写很多if-else,虽然能跑,但是维护起来确实很难受,每次都要在一个方法里面增加逻辑,生怕搞错,要是涉及到支付功能,分分钟炸锅
难调试
我总是不知道之前写的逻辑在哪里,一个方法几百行逻辑,而且是不同功能点冗余在一起!这可能让我牺牲大量时间在这查找调试中
交接容易挨打
当你交接给新同事的时候,这个要做好新同事的白眼和嘲讽,这代码简直是坨翔!这代码简直是个易碎的玻璃,一碰就碎!这代码简直是个世界十大奇迹!
脱下if-else侠的皮衣
先学习下开发的设计原则
单一职责原则(SRP)
就一个类而言,应该仅有一个引起他变化的原因
开放封闭原则(ASD)
类、模块、函数等等应该是可以扩展的,但是不可以修改的
里氏替换原则(LSP)
所有引用基类的地方必须透明地使用其子类的对象
依赖倒置原则(DIP)
高层模块不应该依赖底层模块
迪米特原则(LOD)
一个软件实体应当尽可能的少与其他实体发生相互作用
接口隔离原则(ISP)
一个类对另一个类的依赖应该建立在最小的接口上
在学习下设计模式
大致可以分三大类:创建型,结构型,行为型
创建型:工厂模式 ,单例模式,原型模式
结构型:装饰器模式,适配器模式,代理模式
行为型:策略模式,状态模式,观察者模式
为了尽快脱掉这个if-else的皮衣,我们就先学习一种比较容易接受的设计模型:策略模式
策略模式
举个例子
- 当购物类型为“苹果”时,满 100 - 20,不满 100 打 9 折
- 当购物类型为“香蕉”时,满 100 - 30,不满 100 打 8 折
- 当购物类型为“葡萄”时,满 200 - 50,不叠加
- 当购物类型为“梨”时,直接打 5 折
然后你根据传入的类型和金额,写一个通用逻辑出来,
当我是if-else侠的时候,我估计会这样写:
funcion getPrice(type,money)
//处理苹果
if(type == 'apple'){
if(money >= 100){
return money - 20
}
return money * 0.9
}
//处理香蕉
if(type == 'banana'){
if(money >= 100){
return money - 30
}
return money * 0.8
}
//处理葡萄
if(type == 'grape'){
if(money >= 200){
return money - 50
}
return money
}
//处理梨
if(type == 'pear'){
return money * 0.5
}
}
然后我们开始来分析问题:\
- 违反了
单一职责原则(SRP)
一个方法里面处理了四个逻辑,要是里面的哪个代码块出事了,调试起来也麻烦 - 违反了
开放封闭原则(ASD)
假如我们要增加多一种水果的逻辑,就又要在这个方法中修改,然后你修改完这个方法,就跟测试说,我在这个方法增加了多一个种水果,可能要重新回归这个方法,那你看测试增加了多少工作量
改造考虑:消灭if-else, 支持扩展但是不影响原本功能!
const fruitsPrice = {
apple(money){
if(money >= 100){
return money - 20
}
return money * 0.9
},
banana(money){
if(money >= 100){
return money - 30
}
return money * 0.8
},
grape(money){
if(money >= 200){
return money - 50
}
return money
},
pear(money){
return money * 0.5
}
}
首先定义一个fruitPrice对象,里面都是各种水果价格的映射关系
然后我们调用的时候可以这样
function getPrice(type,money){
return fruitsPrice[type](money)
}
当我们要扩展新水果的时候
fruitsPrice.orange = function(money){
return money*0.4
}
综上所述: 用策略模式重构这个原本的逻辑,方便扩展,调试,清晰简明,当然这只是一个模式重构的情况,可能还有更优的情况,靠大家摸索
本文转载于:
https://juejin.cn/post/7239267216805871671
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

记录--卸下if-else 侠的皮衣!- 策略模式的更多相关文章
- Java设计模式学习记录-策略模式
策略模式 策略模式的定义是:定义了一系列的算法,把它们一个个的封装起来,并且使它们可相互替换,让算法可以独立于使用它的客户而变化. 设计原则是:把一个类中经常改变或者将来可能会经常改变的部分提取出来作 ...
- Head First设计模式之策略模式(Strategy Pattern)
前言: 刚刚开始学习设计模式,之前也接触过一些,但是从来都没有系统的学过,这次打算好好的学习一下.这里就当是对学习过程的一个记录.整理,以便可以在以后不时的温故知新. 这一节采用一个鸭子的示例,层层推 ...
- Java设计模式1——策略模式(Strategy Pattern)
最近觅得一本好书<您的设计模式>,读完两章后就能断言,一定是一头极品屌丝写的,而且是专写给开发屌丝男的智慧枕边书,小女子就委屈一下,勉强看看,人笨,谁让他写得这么通俗易懂呢!为了加深理解, ...
- 策略模式(strategy pattern)
策略模式在java集合中的TreeSet和TreeMap中得到了很好的应用,我们可以实现Comparator接口实现Compareto()方法来定义自己的排序规则,然后通过TreeSet,TreeMa ...
- Java设计模式6:策略模式
策略模式 策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立类中,从而使得它们可以相互替换.策略模式使得算法可以在不影响到客户端的情况下发生变化. 策略模式的结构 策略模式是对算法的包 ...
- Android设计模式之命令模式、策略模式、模板方法模式
命令模式是其它很多行为型模式的基础模式.策略模式是命令模式的一个特例,而策略模式又和模板方法模式都是算法替换的实现,只不过替换的方式不同.下面来谈谈这三个模式. 命令模式 将一个请求封装为一个对象,从 ...
- Java设计模式(学习整理)---策略模式
1. 模式定义 把会变化的内容取出并封装起来,以便以后可以轻易地改动或扩充部分,而不影响不需要变化的其他部分: 2.模式本质: 少用继承,多用组合,简单地说就是:固定不变的信息 ...
- 命令模式 & 策略模式 & 模板方法
一.策略模式 策略模式:封装易变化的算法,可互相替换. GoF<设计模式>中说道:定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换.该模式使得算法可独立于它们的客户变化. 比如 ...
- 策略模式设计模式(Strategy)摘录
23种子GOF设计模式一般分为三类:创建模式.结构模型.行为模式. 创建模式抽象的实例.一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将 ...
- 设计模式浅谈----策略模式(c#及java实现)
一.何为策略模式 策略模式是行为型模式的一种,主要用于需要使用不同的算法来处理不同的数据对象时使用,是一种可以在运行时选择算法的设计模式.也称为政策模式. 主要解决:在有多种算法相似的情况下,使用 i ...
随机推荐
- [Java]Java类中的各元素初始化顺序
Java类中各元素的初始化顺序 初始化的原则是: 先初始化静态部分,再初始化动态部分:(先静再动) 先初始化父类部分,后初始化子类部分:(先父再子) 先初始化变量,次初始化代码块,再初始化构造器:(先 ...
- JS 这一次彻底理解冒泡排序
壹 ❀ 引 在面试环节中,算法总是逃不掉的一关,对于我这种非班科出生且大学不接触数学的人来说,逻辑思维方面确实较为欠缺,昨晚跟百度的同学聊到凌晨,自我感觉差距较大,受了不小打击,所以决心抓一抓算法,做 ...
- 使用sqlmap执行SQL注入并获取数据库用户名
Sqlmap介绍 sqlmap支持MySQL, Oracle,PostgreSQL, Microsoft SQL Server, Microsoft Access, IBM DB2, SQLite, ...
- 高并发时为什么推荐ReentrantLock而不是synchronized
目录 1.最初的 synchronized 2.synchronized 的优化 3.但是,JAVA的最终答案 JDK 21 LTS 来了 1.最初的 synchronized 它默认对临界资源添加重 ...
- iptables临时控制某ip访问权限
iptables -A INPUT -p tcp -s {src_ip} --dport 80 -j ACCEPT iptables -A INPUT -p tcp -s {src_ip} --dpo ...
- CentOS8安装Docker报错问题解决
问题描述 CentOS版本:8.5.2111. # cat /etc/redhat-release CentOS Linux release 8.5.2111 安装准备: # 安装所需软件包 sudo ...
- django学习第十四天--Forms和ModelForm
Forms和ModelForm 进行数据校验,先看数据校验的过程 注册页面图解: 前端为了用户体验会做一些校验,不满足校验要求会报错 服务端也会对数据进行一些校验,不满足校验要求会报错 数据库也会对数 ...
- python装饰器保留原有函数名称和属性functools.wraps()
# python装饰器在实现的时候,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),为了不影响,python的functools包中提供了一个叫wraps的decorator来消 ...
- 问题解决:由于找不到msvcr110.dll,无法继续执行代码
报错 解决 下载地址:https://www.microsoft.com/zh-cn/download/details.aspx?id=30679
- 使用矩池云 Docker 虚拟机安装VNC、Conda、Python及CUDA
矩池云虚拟机支持 Docker 使用,但是由于虚拟机目前不支持启动时传递环境变量来设置VNC.Jupyterlab 连接密码,所以我们没有创建相关基础镜像(设置固定密码容易泄漏),下面给大家介绍手动安 ...
