《设计模式之美》第二章 总结

本文详细阐述了面向对象编程的核心概念,包括封装、抽象、继承和多态,以及如何进行面向对象分析、设计和编程。讨论了OOA/OOD的区别,接口与抽象类的使用,以及面向过程与函数式编程的对比。还探讨了如何在实际项目中运用这些原则,如接口而非实现编程和组合优于继承的原则。
摘要由CSDN通过智能技术生成

《设计模式之美》总结

第二章 面向对象编程范式

2.1 当我们在谈论面向对象时,我们在谈什么

2.1.1 面向对象编程和面向对象编程语言
面向对象编程语言:
1. 以类或对象作为组织代码的基本单元,并将封装、继承、抽象、多态4个特性作为代码的设计和实现的基石;
2. 有现成的语法机制能方便地实现面向对象编程的4大特性;
2.1.2 非严格定义的面向对象编程语言
2.1.3 面向对象分析和面向对象设计
面向对象分析:弄清楚做什么
面向对象设计:弄清楚怎么做
面向对象编程:将分析和设计的结果翻译成代码
2.1.4 关于UML的说明

2.2 封装、抽象、继承和多态为何而生

2.2.1 封装
定义:信息隐藏或数据访问保护;
实现方式:类通暴露有限的访问接口,授权外部仅能通过类提供的方式(或者称为函数)来访问内部信息或数据;
需要语言本身提供一定的语法支持:访问权限控制;
存在的意义:提供有限的方法,提高类的易用性;
解决的问题:防止代码不可控,到处都能修改;
2.2.2 抽象
定义:隐藏方法的内部实现,让调用者只需要关心方法提供了什么功能;
编程语言工具:抽象类、接口,函数本身也是一种抽象;
应用场景:抽象是一种设计思想,可以用在代码编程,也可以用在架构设计上,很多原则体现了抽象这种设计思想:基于接口而非实现编程、开闭原则、代码解耦等;
解决的问题:抽象和封装都是人类在处理复杂系统的有效手段;忽略一些非关键性的实现细节,只关注功能而不关注实现的设计思路,可以帮我们的大脑过滤掉许多非必要的信息;
2.2.3 继承
意义:代码复用;
解决的问题:编码重复编写相同的代码;
副作用:过度使用继承、继承层次过深、过复杂会降低可读性和可维护性;子类和父类耦合,修改父类会影响子类;
2.2.4 多态
定义:在代码运行中,用子类替换父类,并调用子类的方法;
实现机制:
1. 要支持父类对象引用子类对象;
2. 要支持继承;
3. 要支持子类重写父类中的方法;
应用:是很多设计模式、设计原则和编程技巧的代码实现基础,比如策略模式、基于接口而非实现编程、依赖倒置原则、里氏替换原则和利用多态去掉if-else;

2.3 如何进行面向对象分析、面向对象设计和面向对象编程

如何进行面向对象分析:
1. 基础分析
2. 第一轮分析优化
3. 第二轮分析优化
4. 第三轮分析优化
如何进行面向对象设计:
1. 划分职责进而识别有哪些类:类是对事物的建模,罗列名词,拆解成单一职责的功能点,
2. 定义类及其属性和方法:先将识别出的需求描述中的动词作为候选的方法,再进一步过滤和筛选;
3. 定义类之间的交互关系:泛化、实现、聚合、组合、关联、依赖
4. 将类组装起来并提供执行入口;
先给出一个“粗糙”的设计方案,再在这个基础上进行迭代优化;
优化方法:
1. 不是所有名称都定义为属性;
2. 挖掘没有出现在功能点描述中的属性;
3. 添加在功能点描述里没有提到的方法;
软件设计的自由度很大,这也是软件设计的复杂之处;

2.4 面向对象编程与面向过程编程和函数式编程之间的区别

面向过程:以过程(方法、函数和操作)作为组织代码的基本单元,以数据(成员变量、属性)与方法相分离为主要特点;通过拼接一组顺序执行的方法来操作数据实现一项功能;
面向过程和面向对象的区别:
1. 面向对象更适合应对大规模复杂程序的开发;
2. 面向对象以类为思维对象;
3. 面向对象提供了一种模块化的代码组织方式;
4. 面向对象风格代码易复用、易扩展和易维护;
5. 面向对象语言更加人性化、高级和智能:面向对象的编程套路、处理问题的方式完全不一样;面向对象思考的是如何给业务建模,如何将真实世界映射为类,这让我们能聚焦于业务本身;
函数式编程:
适用场景:科学计算、数据处理、统计分析;
特点:函数是无状态的,函数内部涉及的都是局部变量,不共享成员变量和全局变量;执行结果只与入参有关;
语言工具:stream类,Lambda表达式,函数接口(将函数包裹在接口中,当作变量来使用,里面只包含一个未实现的方法)
差异:面向对象侧重于代码模块的设计,面向过程和函数式侧重于具体的实现细节;

2.5 哪些对象看似面向对象编程风格,实则面向过程风格

1. 滥用getter、setter方法(违反封装特性)
2. 滥用全局变量和全局方法;
3. 定义数据和方法分离的类:VO\BO\Entity等只定义数据不定义方法(贫血模式)

面向过程是面向对象的基础:类是面向对象,类里面的方法是面向过程;

2.6 基于“贫血”模型的传统开发模式是否违背OOP

MVC模式就是贫血模型,贫血模型将数据和操作分离,破坏了面向对象的封装特性,属于面向过程风格;
领域驱动设计(DDD)用于指导服务划分;
DDD基于充血模型,Service层包含Service类和Domain类,Domain类既包含数据又包含业务逻辑,而service层变得很单薄。贫血模型重service类,轻BO类;充血模型轻Service类,重Domain类;
基于传统贫血模型开发的原因:
1. 大部分情况下业务系统都比较简单;
2. 充血模型设计难度比贫血模型大
3. 思维已固化,转型有成本,在没遇到痛点情况下,很多程序员不愿意做;
DDD适用场景:复杂的系统开发,比如利息计算模型、还款模型等复杂的金融系统;
两种开发模式会导致不同的开发流程,领域模型相当于可复用的业务中间层,新功能需求的开发都是基于这一层。系统越复杂,对代码的复用性、易维护性要求越高。

2.7 接口和抽象类:如何使用普通类模拟接口和抽象类

接口和抽象类的区别:接口表示has-a关系,类表示is-a关系;接口也叫协议,相当于一个功能列表;
抽象类解决的问题:代码复用+强制子类实现抽象方法;
差异:抽象类是自下向上的设计思路,先有子类的代码重复,再抽象出上层的父类,而接口则相反,它是自上而下的设计思路,先有接口,后有具体实现;

2.8 基于接口而非实现编程:有没有必要为每个类都定义接口

这里的接口可以理解为编程语言的接口或抽象类;
封装不稳定的实现,暴露稳定的接口,将接口和实现分离,能够有效提高代码质量;降低耦合性,提高扩展性;
软件开发中比较大的挑战是:如何应对需求的不断变化;抽象是提高代码扩展性、灵活性和可维护性的有效手段。
接口的初衷:将接口和实现分离,封装不稳定的实现,暴露稳定的接口;
避免滥用接口:某个功能只有一种实现方式,未来也不可能被其他实现方式替换,这就没必要用接口;

2.9 组合优于继承:什么情况下可以使用继承

继承的问题:继承层次过深、继承关系过复杂,会影响代码的可读性、可维护性;
如何解决继承的问题:组合、接口、委托;组合和接口可以替代继承的is-a;多态可以利用接口实现;代码复用可以使用组合和委托实现;
继承改组合,需要进行更细粒度的拆分,会增加代码的复杂度和维护成本;
使用继承的场景:类之间的继承结构稳定,不会轻易改变,而且继承层次比较浅,最多有两层继承关系,继承关系不复杂,反之就不要使用继承;
一定要使用继承的场景:假如不能改变参数的入参类型,而入参又非接口,为了支持多态,只能用继承,比如使用外部的方法,自己没有代码,只能如此操作;
使用原则:控制好各自的副作用,发挥他们各自的优势,在不同的场合下,恰当地选择使用继承或组合;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值