设计模式之美笔记1 淩亂°似流年 2023-03-01 12:49 7阅读 0赞 > 记录学习王争的设计模式之美 课程 笔记和练习代码,以便回顾复习,共同进步 ### 文章目录 ### * * 1. 为什么要学习设计模式 * 2. 如何评价代码质量的高低 * * 1. 简单的描述词汇 * 2. 最常用的评价标准 * * 1. 可维护性maintainability * 2. 可读性readability * 3. 可扩展性extensibility * 4. 灵活性 flexibility * 5. 简洁性 simplicity * 6. 可复用性reusability * 7. 可测试性testability * 3. 最重要的三条 * 3. 面向对象、设计原则、设计模式、编程规范、重构五者的关系 * * 1. 面向对象 * 2. 设计原则 * 3. 设计模式 * * 1. 创建型 * 2. 结构型 * 3. 行为型 * 4. 编程规范 * 5. 代码重构 * 6. 关系 * 4. 面向对象 * * 1. 概念 * 2. 封装、抽象、继承和多态分别解决的编程问题 * * 1. 封装特性 * 2. 抽象特性 * 3. 继承特性 * 4. 多态特性 * 3. 面向对象编程相比面向过程编程的优势 * 4. 三种违反面向对象编程风格的典型代码设计 * * 1. 滥用getter、setter方法 * 2. Constants类、Utils类的设计问题 * 3. 基于贫血模型的开发模式 * 5. 接口和抽象类 * * 1. 抽象类和接口的语法特性 * 2. 抽象类和接口的存在的意义 * 3. 抽象类和接口的应用场景区别 * 6. 基于接口而非实现编程 * 7. 继承和组合 * * 1. 为什么不推荐使用继承 * 2. 组合相比继承的优势 * 3. 如何判断该用组合还是继承 * 4. 思考 * 8. 贫血模型和充血模型 * * 1. 贫血模型 * 2. 充血模型 * 3. 领域驱动设计 ## 1. 为什么要学习设计模式 ## * 应对面试中的设计模式相关问题 * 告别写被人吐槽的烂代码 * 提高复杂代码的设计和开发能力 * 让读源码、学框架事半功倍 * 为职场发展做铺垫 投资要趁早,才能尽早享受复利。早点学习,以后的项目都可以拿来锻炼,每写一行代码,都是对内功的利用和加深,受益整个职业生涯。 ## 2. 如何评价代码质量的高低 ## ### 1. 简单的描述词汇 ### 灵活性flexibility、可扩展性extensibility、可维护性maintainability、可读性readability、可测试性特testability、模块化modularity、高内聚低耦合high cohesion loose coupling、高效high efficiency、高性能high performance、安全性security、兼容性compatibility、易用性usability、整洁clean、清晰clarity、简单simple、直接straightforward、少即是多less code is more、文档详尽well-documented、分层清晰well-layerd、正确性correctness、bug free、健壮性robustness、鲁棒性robustness、可用性reliability、可伸缩性scalability、稳定性stability、优雅elegant… ### 2. 最常用的评价标准 ### #### 1. 可维护性maintainability #### 维护无非就是修改bug、修改老的代码、添加新的代码之类的工作。代码易维护是指,在不破坏原有代码设计、不引入新的bug的情况下,能快速修改或添加代码。 侧面评价,如果bug容易修复,修改、添加功能能够轻松完成,可以主观的认为代码对我们来说易维护;如果修改一个bug,修改、添加一个功能,需要耗费很长时间,可以认为不易维护。 #### 2. 可读性readability #### 代码被阅读的次数远超被编写和执行的次数。可读性在非常大的程度上影响代码的可维护性,首先要读懂代码,否则很容易引入新bug。 需要看是否符合编码规范、命名是否达意、注释是否详尽、函数是否长短合适、模块划分是否清晰、是否符合高内聚低耦合等。 code review是个很好的检查代码可读性的手段,如果同事可轻松的读懂你写的代码,说明可读性很好;如果读你的代码时,有很多疑问,说明可读性有待提高。 #### 3. 可扩展性extensibility #### 代码预留了一些功能扩展点,可以把新功能代码,直接插到扩展点,而不需要为了添加一个功能大动干戈,改动大量的原始代码。 #### 4. 灵活性 flexibility #### 几个场景: 当添加一个新的功能代码时,原有的代码已经预留好了扩展点,不需要修改原有的代码,只要在扩展点上添加新的代码即可,可以说代码写的很灵活。 当要实现一个功能时,发现原有代码中,已经抽象出了很多底层可复用的模块、类等代码,直接拿来用,除了说代码易复用外,可以说代码写的很灵活。 当使用某组接口时,如果这组接口可应对各种使用场景,满足各种不同的需求,除了说接口易用,还可以说这个接口设计的很灵活。 #### 5. 简洁性 simplicity #### KISS原则:`keep it simple,stupid`。尽量保持代码简单。代码简单、逻辑清晰意味着易读易维护。 **思从深而行从简,真正的高手能云淡风轻的用最简单的方法解决最复杂的问题**,这也是编程老手跟编程新手的本质区别之一。 #### 6. 可复用性reusability #### 尽量减少重复代码的编写,复用已有的代码。继承、多态存在的目的之一,就是为了提高代码的可复用性;单一职责原则也跟代码复用性有关;重构技巧中解耦、高内聚、模块化等都能提高代码的可复用性。可复用性是很多设计原则、思想、模式所要达到的最终效果。 代码的可复用性跟DRY(Don’t Repeat Yourself)这个设计原则的关系很紧密。 #### 7. 可测试性testability #### 代码的可测试性差,比较难写单元测试,基本上说明代码设计有问题。 ### 3. 最重要的三条 ### 可维护性、可读性、可扩展性是最重要的三个评价标准。 > 还有一个易定位,是否有打印详细的日志,是否有可快速定位问题的debug点 ## 3. 面向对象、设计原则、设计模式、编程规范、重构五者的关系 ## ### 1. 面向对象 ### * 面向对象的四大特性:封装、抽象、继承和多态 * 面向对象编程和面向过程编程的区别和联系 * 面向对象分析、面向对象设计、面向对象编程 * 接口和抽象类的区别和各自的应用场景 * 基于接口而非实现编程的设计思想 * 多用组合少用继承的设计思想 * 面向过程的贫血模型和面向对象的充血模型 ### 2. 设计原则 ### 是指导我们代码设计的一些经验总结,需要掌握设计初衷,能解决哪些编程问题,有哪些应用场景。 常用的 * SOLID原则-SRP单一职责原则 * SOLID原则-OCP开闭原则 * SOLID原则-LSP里式替换原则 * SOLID原则-ISP接口隔离原则 * SOLID原则-DIP依赖倒置原则 * DRY原则 * KISS原则 * YAGNI原则 * LOD原则 ### 3. 设计模式 ### 大部分要解决的都是代码的可扩展问题,要了解都能解决哪些问题,掌握典型的应用场景,懂的不过度使用。 23种三大类 #### 1. 创建型 #### 常用:单例模式、工厂模式(工厂方法和抽象工厂)、建造者模式 不常用:原型模式 #### 2. 结构型 #### 常用的:代理模式、桥接模式、装饰者模式、适配器模式 不常用:门面模式、组合模式、享元模式 #### 3. 行为型 #### 常用的:观察者模式、模板模式、策略模式、职责链模式、迭代器模式、状态模式 不常用:访问者模式、备忘录模式、命令模式、解释器模式、中介模式 ### 4. 编程规范 ### 如代码大全等书籍,参考阿里巴巴编程规范即可 ### 5. 代码重构 ### 只要软件不断迭代,需求的变化,代码的堆砌,原有的设计必定存在各种问题,就需要持续的重构,保持代码质量不下降,避免代码腐化。 重构的工具就是前面的面向对象设计思想、设计原则、设计模式、编码规范。其实,设计思想、设计原则、设计模式一个最重要的应用场景就是重构的时候。 重构要掌握的: * 重构的目的why、对象what、时机when、方法how * 保证重构不出错的技术手段:单元测试和代码的可测试性 * 两种不同规模的重构:大重构(大规模高层次)和小重构 ### 6. 关系 ### 面向对象编程因为其具有丰富的特性(封装抽象继承多态),可实现很多复杂的设计思路,是很多设计原则、设计模式等编码实现的基础。 设计原则是指导代码设计的一些经验总结,对某些场景下,是否应用某种设计模式,有指导意义,如开闭原则是很多设计模式(策略、模板等)的指导原则 设计模式是针对开发中经常遇到的问题,总结的解决方案或设计思路。目的是提高代码的可扩展性。抽象程度上,设计原则比设计模式更抽象,设计模式更具体、更加可执行。 编程规范解决代码的可读性问题,相对设计原则、设计模式更加具体、更偏重代码细节、更能落地。小重构的理论基础就是编程规范。 重构用到的就是上述的理论。 ## 4. 面向对象 ## ### 1. 概念 ### * 面向对象编程 面向对象编程,OOP,Object Oriented Programming,是一种编程范式或编程风格,以类或对象作为组织代码的基本单元,并将封装、抽象、继承、多态四个特性,作为代码设计和实现的基石。 * 面向对象编程语言 面向对象编程语言,OOPL,Object Oriented Programming Language,是支持类或对象的语法机制,并有现成的语法机制,能方便的实现面向对象编程四大特性的编程语言。 * 面向对象分析和面向对象设计 面向对象分析就是要搞清楚做什么,面向对象设计就是搞清楚怎么做,两个阶段最终的产出是类的设计,包括程序被拆解为哪些类,每个类有哪些属性方法、类与类之间如何交互等。 ### 2. 封装、抽象、继承和多态分别解决的编程问题 ### #### 1. 封装特性 #### 封装也叫信息隐藏或者数据访问保护。类通过暴露有限的访问接口,授权外部仅能通过类提供的方式来访问内部信息或数据。 需要编程语言提供权限访问控制语法来支持,如java的private、protected、public关键字。 封装存在的意义: * 保护数据不被随意修改,提高代码的可维护性 * 只暴露有限的必要接口,提高类的易用性 #### 2. 抽象特性 #### 抽象是讲如何隐藏方法的具体实现,让使用者只需要关心方法提供了哪些功能,不需要知道这些功能是如何实现的。抽象可通过接口类或抽象类实现,但并不需要特殊的语法机制来支持。 抽象存在的意义: * 提高代码的可扩展性、可维护性,修改实现不需要改变定义,减少代码的改动范围 * 处理复杂系统的有效手段,能有效地过滤不必要关注的信息 #### 3. 继承特性 #### 用来表示类之间的is-a关系,分为两种模式:单继承和多继承。单继承表示一个子类只继承一个父类,多继承表示一个子类可继承多个父类。为实现继承的特性,编程语言提供特殊的语法机制来支持。 继承主要用来解决代码复用的问题。 #### 4. 多态特性 #### 多态是指子类可替换父类,在实际的代码运行过程中,调用子类的方法实现。多态需要编程语言提供特殊的语法机制实现,如继承、接口类、duck-typing。 多态可提高代码的可扩展性和复用性,是很多设计模式、设计原则、编程技巧的代码实现基础。 ### 3. 面向对象编程相比面向过程编程的优势 ### * 对大规模复杂程序的开发,程序的处理流程并非单一的一条主线,而是错综复杂的网状结构。面向对象编程比起面向过程编程,更能应对这种复杂类型的程序开发 * 面向对象编程相比面向过程编程,具有更加丰富的特性(封装、抽象、继承、多态),利用这些特性编写的代码,更加易扩展、易复用、易维护 * 从编程语言跟机器打交道的方式的演进规律可以总结:面向对象编程语言比起面向过程编程语言,更加人性化、更加高级、更加智能 ### 4. 三种违反面向对象编程风格的典型代码设计 ### #### 1. 滥用getter、setter方法 #### 在设计实现类的时候,除非真的需要,否则尽量不要给属性定义setter方法,此外,尽管getter方法相对setter安全,但如果返回的是集合容器,也要防范集合内部数据被修改的风险 > 如java的Collections.unmodifiableList()方法,让getter返回一个不可被修改的unmodifiableList容器,但仍可修改内部的对象 #### 2. Constants类、Utils类的设计问题 #### 尽量做到职责单一、定义一些细化的小类,如RedisConstants、FileUtils,而不是一个大而全的Constants类。此外,如果能将这些类的属性和方法,划分归并到其他业务中,最好不过,提高内聚性和代码的可复用性。 #### 3. 基于贫血模型的开发模式 #### MVC模式,数据和操作分开定义在VO/BO/Entity和Controller/Service/Repository中。 ### 5. 接口和抽象类 ### #### 1. 抽象类和接口的语法特性 #### 抽象类不允许被实例化,只能被继承。可以包含属性和方法。方法既可以包含代码实现,也可以不包含代码实现。不包含代码实现的方法叫抽象方法。子类继承抽象类,必须实现抽象类的所有抽象方法。接口不能包含属性,只能声明方法,方法不能包含代码实现。类实现接口的时候,必须实现接口声明的所有方法。 #### 2. 抽象类和接口的存在的意义 #### 抽象类是对成员变量和方法的抽象,是一种is-a的关系,是为了解决代码复用问题。接口仅仅是对方法的抽象,是一种has-a的关系,表示具有一组行为特征,是为了解决解耦问题,隔离接口和具体的实现,提高代码的扩展性。 #### 3. 抽象类和接口的应用场景区别 #### 什么时候用抽象类,什么时候用接口?判断标准:如果表示一种is-a关系,并且为了解决代码复用问题,用抽象类;如果表示has-a关系,并且为了解决抽象而非代码复用问题,用接口 ### 6. 基于接口而非实现编程 ### 1. 基于接口而非实现编程,这条原则的另一个表述方式,是**基于抽象而非实现编程**。后者的标书方式更能体现这条原则的设计初衷。做软件开发时,一定要有抽象意识、封装意识、接口意识。越抽象、越顶层、越脱离具体某一实现的设计,越能提高代码的灵活性、扩展性、可维护性。 2. 定义接口的时候,一方面,命名要足够通用,不能包含跟具体实现相关的字眼;另一方面,与特定实现有关的方法不要定义在接口中。 3. 这条原则,不仅可指导非常细节的编程开发,还能指导更上层的架构设计、系统设计等。如服务器和客户端之间的“接口”设计、类库的“接口”设计。 > 相比于has-a,bahave-like更形象 ### 7. 继承和组合 ### #### 1. 为什么不推荐使用继承 #### 继承是面向对象的四大特性之一,用来表示类之间的is-a关系,解决代码复用问题。虽然继承有诸多作用,但继承层次过深、过复杂,也会影响到代码的可维护性。这种情况下,应尽量少用,甚至不用继承。 > 经典案例就是鸭子问题,会飞、会叫,木头鸭子 #### 2. 组合相比继承的优势 #### 继承主要有三个作用:表示is-a关系,支持多态特性,代码复用。而这三个作用都可以通过组合、接口、委托三个技术手段达成。此外,组合还能解决层次过深、过复杂的继承关系影响代码可维护性的问题。 #### 3. 如何判断该用组合还是继承 #### 如果类之间的继承结构稳定,层次比较浅,关系不复杂,大胆的使用继承。反之,尽量使用组合。 #### 4. 思考 #### 基于MVC架构开发web应用时,经常在dao层定义entity,service层定义BO(Business Object),在controller层定义vo(view object)。大部分情况下,这三者代码有很大重复,但又不完全相同,如何处理代码重复问题? ### 8. 贫血模型和充血模型 ### #### 1. 贫血模型 #### UserBo是一个纯粹的数据结构,只包含数据,不包含任何业务逻辑。业务逻辑集中在UserService中,通过UserService来操作UserBo。也就是说,service层的数据和业务逻辑,被分割为BO和service两个类中。像UserBo这样,只包含数据,不包含业务逻辑的类,叫做贫血模型(Anemic Domain Model)。这种贫血模型将数据和操作分离,破坏了面向对象的封装特性,是一种典型的面向过程的编程风格。 #### 2. 充血模型 #### 充血模型(Rich Domain Model),数据和对应的业务逻辑被封装到同一个类中。 #### 3. 领域驱动设计 #### 领域驱动设计DDD(Domain Driven Design),主要是用来指导如何解耦业务系统,划分业务模块,定义业务领域模型及其交互。 领域驱动设计用来指导划分服务,因此微服务的兴起,加速了领域驱动设计的盛行。 基于充血模型的DDD开发模式实现的代码,也是MVC三层架构分层,相较传统的MVC,区别在于service层。传统的service层包含service类和bo类,在DDD开发模式中,service层包含service类和Domain类两部分。Domain和Bo的区别在于它是基于充血模型开发的,既包含数据,也包含业务逻辑。而service类变得非常单薄。 总结就是,基于贫血模型的传统的开发模式,重service轻bo;基于充血模型的DDD开发模式,轻service重domain。 DDD开发模式,开发流程,需要事先理清所有的业务,定义领域模型所包含的属性和方法,领域模型相当于可复用的业务中间层。新功能需求的开发,都是基于之前定义好的这些领域模型完成。 > 感觉充血模型很鸡肋,其实想要解决代码复用的问题,有很多思路,如SQL只定义基本的,用mybatis之类的或在service层磊积木;此外,时间成本很重要,程序员水平参差不齐,主流的MVC完全可以满足业务,如果想快速定位问题,也有对策,如重点代码部分写好日志,搭建日志中心,以及pinpoint之类的监控系统即可。
相关 设计模式之美笔记1 > 记录学习王争的设计模式之美 课程 笔记和练习代码,以便回顾复习,共同进步 文章目录 1. 为什么要学习设计模式 2. 如何评价代码质量的高 淩亂°似流年/ 2023年03月01日 12:49/ 0 赞/ 8 阅读
相关 设计模式之美笔记16 > 记录学习王争的设计模式之美 课程 笔记和练习代码,以便回顾复习,共同进步 文章目录 解释器模式 解释器模式的原理和实现 深藏阁楼爱情的钟/ 2022年12月01日 11:53/ 0 赞/ 163 阅读
相关 设计模式之美笔记15 > 记录学习王争的设计模式之美 课程 笔记和练习代码,以便回顾复习,共同进步 文章目录 访问者模式 访问者模式的诞生 我就是我/ 2022年12月01日 05:16/ 0 赞/ 171 阅读
相关 设计模式之美笔记14 > 记录学习王争的设计模式之美 课程 笔记和练习代码,以便回顾复习,共同进步 文章目录 状态模式 背景 什么 水深无声/ 2022年11月30日 15:51/ 0 赞/ 190 阅读
相关 设计模式之美笔记13 > 记录学习王争的设计模式之美 课程 笔记和练习代码,以便回顾复习,共同进步 文章目录 策略模式 策略模式的原理和实现 忘是亡心i/ 2022年11月30日 12:27/ 0 赞/ 175 阅读
相关 设计模式之美笔记12 > 记录学习王争的设计模式之美 课程 笔记和练习代码,以便回顾复习,共同进步 文章目录 观察者模式 原理及应用场景剖析 深碍√TFBOYSˉ_/ 2022年11月30日 04:18/ 0 赞/ 206 阅读
相关 设计模式之美笔记11 > 记录学习王争的设计模式之美 课程 笔记和练习代码,以便回顾复习,共同进步 文章目录 门面模式 门面模式的原理和实现 ゞ 浴缸里的玫瑰/ 2022年11月28日 13:41/ 0 赞/ 200 阅读
相关 设计模式之美笔记10 > 记录学习王争的设计模式之美 课程 笔记和练习代码,以便回顾复习,共同进步 文章目录 序言 代理模式 桥接模式 柔情只为你懂/ 2022年11月28日 10:36/ 0 赞/ 189 阅读
相关 设计模式之美笔记9 > 记录学习王争的设计模式之美 课程 笔记和练习代码,以便回顾复习,共同进步 文章目录 工厂模式 1. 简单工厂 待我称王封你为后i/ 2022年11月28日 00:41/ 0 赞/ 197 阅读
相关 设计模式之美笔记7 > 记录学习王争的设计模式之美 课程 笔记和练习代码,以便回顾复习,共同进步 文章目录 实战1:id生成器的重构 1. 需求背景 女爷i/ 2022年11月25日 13:19/ 0 赞/ 219 阅读
还没有评论,来说两句吧...