• 《面向对象葵花宝典》阅读笔记


    满满的干货!推荐大家购买的一本书,里面很多的内容,都是我编程过程经历过的困惑(相信大家都会遇到),如果早点看到这本书,相信当时我也不会困惑那么久了~所以记录总结一下。
    PS.欲看此书,不必自宫……

    面向对象理论

    面向过程与面向对象

    面向过程是一种以“过程”为中心的变成思想,就是典型的“计算机思维”,其实就是完成一件事情的步骤,就像生成流水线,它是计算机的基石,本身计算机就是按照步骤进行计算的。

    面向对象是一种以“对象”为中心的变成思想,开发更贴近人类的思维特点,更加脱离机器思维,这些对象不需要指定严格的操作顺序,而是指定了这些对象需要完成的任务,以及这些对象如果对外界的的刺激做出反应。我就是我,是颜色不一样的烟火,世界上每个人都是不一样的,但是我们都是人类,按照面向对象的思想,我们都是人类实例化的对象,我们有着不同的处世方法,语言,肤色等等,这才造就了这样丰富的世界,而人类又是继承自哺乳动物的…等等。

    PS:不要从代码的角度去思考面向对象,因为代码到头来也是过程执行的,应该从设计的角度去考虑面向对象,提高软件扩展性。

    为什么要面向对象

    面向对象的特性:抽象、封装、继承、多态。这些特性的核心就是“可扩展性”。有了面向对象,我们可以将变化带来的风险控制在有限的范围内,避免产生全流程或者更大范围的影响,从而降低风险。所以面向对象并不是瑞士军刀,只是一个普通的锤子而已,千万不要拿着锤子到处敲……(多数情况适用于大型软件,就别拿他来写算法什么的了)。

    站在你的观察角度,具有相似点的事物就是同一类。
    例如:
    人和猪是同一类么?从哺乳动物的角度,是的。
    人和树是同一类么?从生物的角度,是的。

    所以具体的情况要具体分析

    类=方法+属性

    设计原则:
    1、属性最小化,不可再分(适应性最强)。
    2、方法单一原则,一个方法只做一件事

    对象

    真实存在的就是对象,我就是对象,而人是一个类,真正在软件运行中的是”对象“,而不是”类“,类只是程序员抽象出来的东西。
    程序员就是软件世界的上帝~这也是为什么那么多人痴迷的原因。

    接口

    interface,是一组相关的交互功能定义集合。它只能声明方法,不能直接实例化,需要类继承之后,再通过实现类进行实例化,实例化之后也只能调用接口方法。

    从软件交互上看,API接口,可以让我们的程序与其他程序交互,但是也要符合API文档的接口规范和数据定义~

    从硬件交互上看,USB接口,可以接入很多种设备,但是他们都要遵循USB接口协议标准。

    从软件设计上看,更趋近于类中的“行为”规范,例如:有鲨鱼,鲤鱼这2种鱼类的子类,他们肯定只会在水里游吧?不会飞吧?,所以在设计鱼类的时候,我需要定义鱼的接口,让子类都强制实现接口,只能游,不能飞,要是谁能飞,这就违反了鱼类的常理了!(当然,飞鱼是可以飞的,它已经进化了…但是它依旧还是会在水里游的,这个飞的技能,其他鱼类不会,是他自己实现功能),这时候,程序员就是上帝,我要下发个命令让鱼儿们都游起来,生命在于运动~,我不管是鲨鱼还是鲤鱼,你们肯定都会在水里游,这时我只需要调用游的接口。

    抽象类

    有接口了,我还要抽象类干什么?他们好像都一样啊?

    同样,抽象类只能继承,不能直接实例化,但是,抽象类相对于接口,可以有自己的属性、方法,其中还可以声明抽象方法(只有声明,没有定义,子类必须实现定义)
    如果说类是从现实对象抽象出来的,那么抽象类就是从类抽象出来的。有什么用?抽象类本质还是类,强调一组事物的相似性,包括属性和方法的相似性,接口只强调方法相似性,用抽象类可以大大减少工作量和代码量!

    例如:
    设计网站注册的类,有用户名、密码这两个属性,有验证、注册两个方法。先验证,再注册,但是这个时候,用户名被分为手机号,昵称,邮箱三种,所以验证的方式都不同,而其他方法属性都相同,怎么办?将这个网站注册类再抽象出来一个抽象类,仅仅将验证方法设计成抽象方法,这样,在继承这个抽象类的时候,我们只需要实现抽象方法即可,其他内容都继承父类。什么?你说把验证方法弄成接口?那你实例化的对象,只能调用验证方法,最后怎么设置属性,怎么注册成功?

    我们可以看出,抽象类看起来是介于类和接口直接的概念,同时具备类和接口的部分特性。

    抽象

    抽取多个对象中或者类中比较像的部分,抽象最主要的作用是“划分类别”,而划分类别主要目的是“隔离关注点,降低复杂度”。因为这个世界太复杂了……。
    第一层:对象抽象成类,例如黑人、白人抽象出人类,野猪、土猪抽象出猪类。
    第二层:类抽象成超类,人类和猪类再抽象出一层,即动物类。

    在实际设计中,抽象的层次不限,根据业务需要来定。

    封装

    为什么要封装?世界上每个人都有隐私,苹果也不会把他的IOS系统源码公开。
    对于属性来说主要原因就是保护隐私!
    对于方法来说,就是隔离复杂度,每个类只关心自己的功能即可,就像空调一样,我按开关,你出冷风就行了,我才不管你内部是怎么运行的,不然哪里还有人会用空调?

    面向对象封装分为三种:public(公开)、protected(子类公开)、private(私有)

    继承

    某种意义上就是遗传。抽象和继承是前后衔接的关系,先有抽象,后有继承。有了继承,我们可以实现很强的扩展,并且可以减少很多代码量,只不过调试,或者看代码的时候,非常的繁琐,经常要跑到父类查看相关定义。

    多态

    即多种形态,面向对象中可以理解为“子类的调用,可以用父类代替”(因为子类都实现了父类的方法呀)
    例如:人、猪、狗,都是动物,都会跑,这个是有用个方法,可以直接用动物类定义对象参数类型
    run(Animal obj)
    这个时候,我们不管传入那个动物的参数,都可以跑起来,因为他们都是动物的不同形态。

    多态屏蔽了子类对象的差异,使得调用者可以写出通用代码,而无需对每个子类来写不同代码。

    需求模型

    需求!=功能
    需求:对客户来说有价值的事情。
    功能:系统为了实现客户价值而提供的能力。
    需求与功能的区别:只要判断是否对客户有价值。

    例如:POS机,“买单”是需求,“商品扫描”、“金额汇总”、“收银”等是功能,买完单,客户就能带走商品,他不会管你这些功能步骤。
    打印机,“打印”是需求,“进纸”、“设定”、“与电脑连接”是功能。

    需求是项目的开始,是非常重要的,不要到时候你把一坨屎(错误的需求),放到饼干生产线,最后生产出来的还是像饼干一样的屎。

    如果需求错了,那么几乎是要把软件重做一遍。需求很重要

    客户:“我要一只羊”
    记录员:只是记录客户需求,要一只什么样的羊
    分析员:要羊来干什么?哦,拿来烤着吃,客户不会烤羊,需要一只烤好的羊。
    引导页:目前是夏天,火气重,烤羊不太好,换成冰镇啤酒海鲜大餐如何?

    需求分析518方法,我要发~

    5W:when(时间相关),where(地点相关),who(参与者),what(客户想要的输出),why(客户遇到的问题,也是客户提出需求的驱动力)
    其中,why很重要,只有真正理解了客户的需求驱动力,才能解决客户的问题—-“挖掘客户的问题,实现客户价值!”。

    1H:how
    注意,分析需求阶段,不要考虑如何实现需求,how就是用来描述整个需求本身的流程是如何运作的。(用例方法)

    8C:约束与限制
    性能Performance、成本Cost、时间Time、可靠性Reliability、安全性Security、合规性Compliance、技术性Technology、兼容性Compatible

    5W+1H关注功能属性,8C关注质量属性。

    用例方法

    Use Case是用来描述需求的流程。

    写法示例:
    【用例名称】
    【场景】
    Who、Where、When
    【用例描述】
    What、How
    【用例价值】
    Why
    【约束和限制】
    8C

    第一遍写正常处理
    第二遍增加相关步骤的异常情况说明和处理
    第三遍增加替代处理。

    要画UML图吗?

    在学习UML的时候,我也有过疑问,学这些图,好繁琐的样子,到时候做分析的时候,真的有必要画出来吗?,答案是否定的,UML其实就是一种建模语言。你会汉语,不代表你就能写中文小说,你会UML也不能说你一定会做需求分析,不能本末倒置,比如用例图,只是用例的图像化而已,并不能取代用例,我们使用用例图,是为了更好的描述用例。

    更重要的是,用例是客户和公司关于产品的共同认识,需求分析过程中,很少有研发人员参与,对于客户来说,他肯定以自然语言来描述用例,他不懂也不会用UML来描述,所以是否采取画图?那个方式能够更好的服务于需求分析,就用哪种,通常情况都是用纯文本描述。

    PS:用例图其实是用来描述系统用例的集合,并不会详细描述每个用例的具体步骤,活动图和顺序图才是描述步骤的。

    功能提取

    有了用例,都好办,功能提取,仅仅需要把动词提取出来。
    例如:

    功能编号功能描述涉及用例
    001 银行卡验证 取款、存款、余额查询

    领域模型

    领域模型是需求分析到面向对象设计的桥梁。
    是需求所涉及的领域的一个建模,通俗讲也就是业务模型。主要有2个重要的作用
    1、挖掘重要的业务领域概念;
    2、建立业务领域之间的关系。

    在用例中建立领域模型。
    方法:找名称(识别名词、删除不是领域对象的名词)、加属性(属性并没有在用例中明确给出)、连关系(领域模型直接的关系)
    领域模型和类图很像。

    设计模型

    类模型

    照葫芦画瓢
    1、领域类映射
    2、类筛选
    3、名称映射
    4、属性映射
    5、提炼方法
    领域模型中没有方法,方法需要从用例中提炼,即找动词,再进行一次筛选提炼
    6、分配方法

    应用设计原则和设计模式
    依赖倒置
    接口单一
    里氏替换
    迪米特原则(最少知识原则)
    开闭原则

    单抽建工原
    适桥装配外享代
    模命迭观中备解狀策职访

    PS:这里都是需要经验来权衡的

    拆分辅助类
    一般不需要将拆分的辅助类体现在类模型中,仅在编码的时候拆分即可。

    动态模型

    1、状态模型
    主要用于描述对象生命周期的状态变化,通过状态图,可以了解有哪些状态、状态之间如何转换、转换触发条件等。例如电梯状态图。

    2、活动模型
    主要描述一个工作流程或者计算流程,当一个处理流程比较复杂的时候,就需要设计活动模型。即活动图

    3、序列模型
    主要用于描述对象按照时间顺序组织的消息交互过程,即序列图,也称为时序图、顺序图

    4、协作模型
    主要用来描述按照对象之间的关联来组织消息交互过程,和序列模型类似,只是强调点不同,大多数情况使用序列模型

    建模技巧
    不需要面面俱到:我们只需要针对一些关键的、核心的、复杂的业务或者功能进行动态建模。动态模型有多种,每种都有不同的使用场景,并不意味着每个业务或者功能每种模型都要涉及,哪种能够将处理过程描述清楚就用哪种。

    模型!=代码:模型不等于伪码,更不等于代码,主要是指导代码编写

    实现模型

    每种语言的面向对象实现特性也不同,但是编程思想都是一样的,至于具体的实现过程,多动手吧。

    设计原则

    内聚

    指一个模块内部元素彼此结合的紧密程度。

    以类设计为例,假如一个类里面的函数都只依赖本类的其他函数,那内聚性肯定是最好的。

    当模块的元素全部都专注于模块的职责的时候,即使元素间的结合不是很紧密,也符合内聚性的要求。

    内聚分类
    1、偶然内聚
    模块的元素之所以被划分到相同模块,仅仅因为巧合,例如Utils包里面,有很多不同功能的Utils类

    2、逻辑内聚
    元素逻辑上属于一个比较宽泛的类别。例如,鼠标,键盘,都是输入设备,但是本身的职责又不同。

    3、时间内聚
    元素在时间上是相近的。例如一个日志记录里,包含释放资源,记录日志,通知用户,这几个处理在同一个函数里,他们就是时间内聚

    4、过程内聚
    元素必须按照固定“过程顺序”进行处理,与时间内聚相似,只不过时间内聚可以随意调换顺序。

    5、信息内聚
    元素都操作相同的数据,例如增删查改的方法,都操作同一个数据,所以内聚在一起了

    6、顺序内聚
    某些元素的输出是另外元素的输入。就像流水线,上一个环节输出,是下一个环节输入

    7、功能内聚
    元素都是为了完成同一个单一任务,例如,读取文件,其中包括文件存在检查,权限检查,这些方法都是为了读取文件存在的,所以内聚在了一起。

    耦合

    程序模块之间的依赖程度,内聚和耦合是相反的。

    耦合分类
    1、无耦合
    其实就是高内聚的体现,这样效率非常低下,什么东西都要自给自足,不能利用分工合作

    2、消息耦合
    类的方法也就是“消息”,A类调用B类方法,这就是消息耦合

    3、数据耦合
    两个模块之间通过参数传递基本数据(int,string等),例如在教师类中,通过学生ID来查询学生的排名。

    4、数据结构耦合
    上面的int学生ID变成了StudentInfo类(即数据结构)。

    5、控制耦合
    当一个模块可以通过某种方式控制另一个模块。例如通过传入控制参数来控制函数的处理流程或者输出,switch case

    6、外部耦合
    两个模块依赖相同的外部数据格式,通讯协议,设备接口。例如USB,系统与鼠标就形成了外部耦合

    7、全局耦合
    两个模块共享相同的全局数据时,称为全局耦合,例如全局变量。

    8、内容耦合
    当一个模块依赖另一个模块的内容(主要是数据成员),称为内容耦合,这种是“病态耦合”,完全破坏了模块的封装性,例如public成员变量

    高内聚低耦合

    为的就是使类稳定,即变化的风险降到最低。
    内聚与耦合是冲突的,需要在这俩者之间进行平衡。

    类设计原则

    职责单一SRP原则用于指导类的设计 
    开闭原则OCP原则是总的设计指导思想 
    里氏替换LSP原则用以指导类继承的设计 
    接口隔离ISP原则用于指导接口的设计 
    依赖倒置DIP用于指导类的抽象的设计 
    不要过度设计

    设计模式

    PS:对于设计模式的书,推荐《设计模式之禅》
    设计模式解决的是“可复用”的设计问题,对于性能,可靠性,安全性都不是设计模式能解决的。
    设计模式应用的领域是“面向对象”,C语言写设计模式,折腾死你。

    所以不要拿着这把锤子到处敲。

    找到变化、封装变化、举一反三。

    面向对象架构设计

    架构是系统的结构和组织,子系统也是系统,也有自己的架构

    架构设计师为了隔离关注点,降低复杂度,为了分工合作。

    架构=模块+交互。

    面向对象的架构设计流程:
    业务架构->领域架构->软件架构

    业务架构

    问客户,客户比你更清楚希望的系统,理想的情况下,需求分析人员可以很好的解答这个问题。

    例如,铁路售票,至少包括订票,查票,支付,取票等几个部分。

    架构的最雏形就来源于客户的业务系统,是对客户业务系统的模拟。

    业务架构和用例模型一样,其实也是文字描述,比用例模型更抽象,只需要描述业务的整体结构即可,也需要包含约束和限制。

    领域架构

    只需稍微提炼一下业务架构。
    1、提取业务模块
    2、确定业务模块之间的关系。

    然后画图

    软件建构

    1、根据领域架构,将模块增加“子系统”三个字,大致就出现了软件架构图
    2、根据约束和限制,优化系统架构,这需要靠架构师的经验和积累
    3、深思熟虑,全面评估各个备选方案的优劣点,挑选最优的方案。

    面向对象架构设计技巧

    原则

    1、客户需求优先
    例如,老板要你成本控制在1000元,1000元不是扯淡么,那么你可以对老板说:产品无法满足客户需求。
    尚方宝剑,百试百灵。

    2、适当超前
    唯一不变的是变化,首先满足客户需求,再超越客户需求,不要一上来就要设计一个举世无双的系统。

    拆与合

    不管是性能,可用性,复杂新,可扩展性,拆都能搞定,然而难点在于“合”,如何整合?
    拆:拆硬件、拆地点、拆功能
    合:客户端合(客户端将拆分的系统合起来),网络合(通过网络将系统合起来,例如反向代理),中间和(中间件),子系统和(通过接口互相调用)





  • 相关阅读:
    Android Widget桌面组件创建
    Android 音乐播放器。
    android 创建实时文件夹
    Android 中访问网页 webView
    Android 添加快捷方式
    Android闹钟设置
    Android中webView与javascript交互
    Android 通信的桥梁 Intent
    Android 中Notification和NotificationManager的使用
    Android中播放视频
  • 原文地址:https://www.cnblogs.com/leestar54/p/5464011.html
Copyright © 2020-2023  润新知