设计模式-六大原则
设计模式-六大原则
设计模式的六大原则
单一职责原则
Single Responsibility Principle
提示
单一职责原则是实现高内聚、低耦合的指导方针,它是最简单但又最难运用的原则,需要设计人员发现类的不同职责并将其分离,而发现类的多重职责需要设计人员具有较强的分析设计能力和相关实践经验—只有熟悉业务,才能做好设计
案例
动物的故事
多分支的Animal该如何设计
都放在一个类---需要各种判断+分支---肯定不稳定,有很多个原因让他变化---违背了单一职责---拆分成多个类(chicker cow fish)---每个类就都稳定了,都单一职责了同一父类多个类型,其实应该拆开写,而不是都塞在一个类---满足单一职责
银行客户端
Client--->
利率要变,得改类,说明职责不单一---封装利率获取的逻辑到别的类账号验证要变,得改类,说明职责不单一---封装到别的类里面—UserCheckService一个类的多个动作,交给别的类去封装,只负责调用---满足单一职责,增强稳定
心得
优缺点
优点:
缺点:
提示
有所得必有所失,设计师做的,就应该是扬长避短,灵活应用
场景
里氏替换原则
Liskov Substitution Principle
知识点同步
案例
People
总结
依赖倒置原则
Dependence Inversion Principle
案例
学生-手机
Student Play 手机
依赖细节(具体手机),新增手机都需要修改Student---不合理依赖抽象(AbstractPhone),新增的手机都可以用,只要实现了这个抽象类1 一个方法应对更多类型
2 支持扩展新增,保持稳定性
层级多了,依赖细节,一个改动会影响一连串---水波效应依赖抽象,类的改动影响就不会扩散
类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。
分析
依赖倒置原则基于这样一个事实:相对于细节的多变性,抽象的东西要稳定的多。(插头(可以各种造型各种材质)-插排---车子轮胎-17寸18寸19寸—接口大小) 以抽象为基础搭建起来的架构比以细节为基础搭建起来的架构要稳定的多。
抽象指的是接口或者抽象类,细节就是具体的实现类,使用接口或者抽象类的目的是制定好规范和契约,而不去涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。
建议
1 低层模块尽量都要有抽象类或接口,或者两者都有
2 变量的声明类型尽量是抽象类或接口
3 使用继承时遵循里氏替换原则(避免埋雷)
依赖倒置原则的核心就是要我们面向抽象/接口编程,理解了面向抽象/接口编程,也就理解了依赖倒置。
各种工厂的面向抽象---80%的设计模式都跟面向抽象有关现代化开发
IOC已内置—无处不在的IOC---就得有抽象
接口抽象类选择问题
抽象类: 可以包含具体实现---约束+实现
接口: 不能包含具体实现---约束
C#8.0变化
1 方法可以声明public 也可以protected,但不能是private
2 字段还是不能声明
3 以前委托和类不能声明,现在都可以声明了
4 以前不能有具体实现,现在也可以有了
这个有没有意义?
有,而且是颠覆性的—以前都说接口不能变,现在可以直接增加实现---这对有的设计模式就会产生冲击
还需要抽象类吗?
还是需要的,抽象类是 is a
而接口还是can do
抽象类:(父类只有一个) 继承+约束: 其实为了继承,约束是副业 is a---抽象类表述的对象
接口: (接口可以多个) 只是做约束 can do,就可以跨不同类型 ----接口表述的是行为,以及规则
不是语法上的问题,而是语义上的问题
经验
C#8.0后,接口允许有默认实现,会改变很多认知
选择还是以:
抽象类表述的对象
接口表述的是行为和规则
更多时候,选择接口就对了,除非有代码想复用(值得商榷)
接口隔离原则
Interface Segregation Principle
案例
手机-相机
手机:打电话 发短信 看电影 上网 玩游戏 拍照 拍视频导航 支付
平板: 看电影 上网 玩游戏 拍照 拍视频
电视: 看电影 上网 玩游戏
相机: 拍照 拍视频
1 接口太大:不需要的功能也得实现--不合理
2 接口太小:接口众多,还会出现一个对象实现多接口,但不能用3 接口合并:
一定在一起的,要合并(上网-玩游戏 拍照-拍视频); 不需要对外暴露,只暴露一个(一个动作 多个步骤导航---定位-计算路线-语音播报)
通过继承来组合接口,定制大接口
总结
和SRP区别
接口隔离和单一职责的区别:
迪米特法则
Law Of Demeter
案例
学校-班级-学员
1 去掉内部依赖:学校不要直接管student,也不关心细节(BCL基类库类型除外)
2 降低访问修饰符:避免暴露太多细节
3 属性变方法:也是为了保护,可以扩充逻辑
分析
目标都是为了低耦合,高内聚。
耦合的方式很多,依赖、关联、组合、聚合等。其中,我们称出现成员变量、方法参数、方法返回值中的类为直接的朋友,而出现在局部变量中的类则不是直接的朋友。也就是说,陌生的类最好不要作为局部变量的形式出现在类的内部
引入
程序对象的直接朋友太多,还可能会引入一个中介,来完成通信,等于是把直接的朋友给变成间接的朋友 比如:一个人和另一个人聊天,发消息 收消息 选择对象 通过中介来发消息 收消息
门面模式
中介者模式
应用范围
1 小到类与类之间:避免跟局部变量交互
2 到类库和类库之间,三层之间:UI-BLL-DAL,UI和DAL不要通信3 大到系统和系统之间:调用用户数据,只能找用户服务,不能找数据库
开闭原则
Open Closed Principle
由来
面向对象语言是一种静态语言,最害怕变化,会波及很多东西,需要全面测试最理想就是新增类,对原有代码没有改动,原有的代码才是可信的
开闭原则只是一个目标,并没有任何的手段,也被称之为总则
其他5个原则的建议,就是为了更好的做到OCP
开闭原则也是面向对象语言开发一个终极目标
案例
学生学习
1 学生学习,需要增加个公开课的分支,是修改方法增加判断,换成新增一个方法--甚至换成新增一个类----从修改变新增
2 学生学习,需要增加个额外的动作,是修改方法,还是新增方法,或者子类override ----从修改变新增
代码升级顺序
提示
满足OCP的程度排序:
1 修改配置—IOC/工厂使用配置文件
2 增加dll—依赖抽象+反射
3 增加class--
4 增加方法—
5 修改方法
遵循OCP,也会带来很多成本
SRP—为了少修改,多增加
LSP---用父类,减少修改
DIP---使用抽象
LOD---减少修改
ISP---小一点,稳定点
总结
提示
这代表一个系统设计时,对6大原则的一个完成度1234都是正常的
1 第5个有问题,兼而有之,都没照顾好
2 第6个也不好,过犹不及,太夸张了
设计模式六大原则,也只是指导性原则
努力遵循,程序可以更具备扩展性
可以违背,一切为了目标
具体的体会,还需要更多的设计模式来验证