目录
一, 程序, 算法
本质
举例
二, 面向对象, 设计模式
面向接口编程
组合优于继承
三, 依赖倒置和控制反转 (IoC/DIP)
钱
开关和灯
证券交易所
一, 程序, 算法
本质
程序 = 算法 + 数结结构
算法 = 逻辑 + 控制
程序 = 算法 + 数结结构, 这个是众所周知了, 算法这个解释则比较清丽脱俗: 1. 逻辑 2. 控制.
逻辑用来解决实际的问题, 控制决定用什么策略来解决问题, 逻辑是真正意义上的解决问题的算法
控制是一个程序流转的方式, 即程序执行的方式, 并行还是串行, 同步还是异步, 调度不同执行路径或模块, 数据之间的存储关系.
逻辑是是处理什么, 控制是怎么做, 沟通方式是数据结构
举例
表单验证经常的做法是
function check(data) {
名字 = get(data, 名字)
if (名字为空 || 名字长度小于 3) {
return 验证失败, 名字非法
}
密码 = get(data, 密码)
if (密码为空 || 密码长度小于 8) {
return 验证失败, 密码非法
}
邮箱 = get(data, 邮箱)
if (邮箱为空 || 邮箱格式不正确) {
return 验证失败, 邮箱非法
}
...
return 验证通过;
}
这个函数最终逻辑是验证输入数据的合法性, 但是这样其实就是把控制和逻辑耦合在一起了, 随着验证字段的增多, 这个函数会越来越长, 最终造成可读性越来越差, 越来越难维护
更好的分离两者的方法是, 定义一个表单验证器, 如下
var rules = {
名字: ["长度大于 3"],
密码: ["长度大于 8"]
邮箱: ["email 格式"]
- ...
- ]
- };
if 失败结果 = checkRules(rules). 执行 (); 失败结果不为空 {
return 验证失败, 失败结果
}
return 验证通过
这样通过描述验证规则, 得到了一种控制和逻辑之间的解耦, 不用再在 check 里边各种 if else 了.
绝大多数程序复杂混乱的根本原因是业务逻辑和控制逻辑的耦合
二, 面向对象, 设计模式
面向对象, 设计模式的重点就是:
使用接口抽象了具体的实现类, 这样其它类耦合的是接口而不是实现类, 这就是多太, 增加了程序的扩展性
接口也就是一种协议, 就像 HTTP 协议一样, 浏览器和后端的程序都依赖于这一种协议, 而不是具体的实现 (如果是依赖具体实现, 那么浏览器就要依赖后端的编程语言或中间件了, 这就太恶心了). 于是, 浏览器和后端的程序就完全解除依赖关系, 而去依赖一个标准的协议了, 这也是 IoC/DIP 的本质.
23 个设计模式基本就是说了两个面向对象的核心理念: 面向接口编程, 组合优于继承
面向接口编程
使用者不需要知道数据类型, 结构, 算法的细节
使用者不需要知道实现细节, 只需要知道提供的接口
组合优于继承
继承需要给子类暴露一些父类的设计和实现细节, 父类实现的改变会造成子类也需要改变, 而组合则不存在这样的弊端.
我们以为继承主要是为了代码重用, 但实际上在子类中需要重新实现很多父类的方法, 继承更多的应该是为了多态.
三, 依赖倒置和控制反转 (IoC/DIP)
简单说就是要依赖于抽象接口, 不要依赖于具体实现
这就是控制反转, 开关从以前设备的专用开关, 转变到了控制电源的开关, 而以前的设备要反过来依赖开关厂声明的电源接口
钱
从以前的以物易物, 变成了依赖 "钱", 所有的商品都依赖这个 "钱" 的交易协议, 不用再互相依赖了, 整个世界的动作就简单了很多
开关和灯
有一个开关要控制一个灯的开和关, 最直接的方法就是把开关和灯做到一起.
但是, 如果有一天, 我们发现这个开关可能还要控制别的不仅是灯泡的东西, 就会发现开关耦合了灯泡这种类别, 非常不得扩展.
解决方案就是, 造开关工厂根据不需要关心要控制的东西是什么, 只做一个开关, 功能就是把电接通和断开, 不管是手动的, 声控的还是光控, 遥控的, 开关厂和电灯厂依赖于一个标准的通电和断电的接口.
造灯泡的工厂也不关心你用什么样的开关, 只管把灯的电源接口做出来, 开关厂和电灯厂依赖于一个标准通电和断电的接口.
证券交易所
在交易的过程中, 卖家向买家卖东西, 一手交钱一手交货, 基本是要见面的, 这个时候银行出来做担保, 买家先把钱打到银行, 银行让卖家发货, 买家验货后, 银行再把钱打给卖家.
这就是反转控制, 买卖双方把对对方的直接依赖和控制, 反转到了让对方来依赖一个标准的交易模型的接口.
来源: https://www.cnblogs.com/chenqionghe/p/13744796.html