简称Object Oriented Program(OOP)
,指以类或对象作为基础组织单元,遵循封装、继承、多态以及抽象等特性,进行编程。其中面向对象不一定遵循封装、继承、封装和多态等特性,只是前人总结的套路规范
,遵循该套规范,可以快速,准确以及优雅的完成面向对象编程。
软件系统设计的三个阶段:分析、设计以及实现
。在面向对象领域,分别对应着面向对象分析(OOA)
,面向对象设计(OOD)
以及面向对象编程(OOP)
。OOA和OOD主要用于解决:被分为哪些类,类的属性和行为以及类与类之间的组织【交互关系】 等问题。整体来看:OOA -> 做什么
、 OOD -> 怎么做
、OOP -> 将分析和设计翻译为代码的过程
。
本质上就是访问权限控制,哪些内容是允许访问的,哪些是不允许访问的,防止权限的滥用。存在的意义:
对现实世界的直接映射,便于理解, 提高代码的复用性。但要注意继承的层级,层级过深,会降低代码的可读性。
隐藏方法的具体实现。从调用方角度来看,并不关心方法是怎么实现的,只需告诉该方法能做什么即可。类比到现实世界,买车的时候,仅关注车提供的功能,并不关注你是怎么做出来的。 本质: 就是复杂世界或复杂系统提供的信息太多了,有些信息是完全没必要关注的。因此,仅关注你所关心的即可。
实现方式: Java中提供了接口和抽象语法
存在意义: 提高代码可扩展性,可读性和可维护性;是处理复杂系统的有效手段。
指子类可以灵活替换父类,需要编程语言特殊语言支持。类似于Java的接口、抽象类等。
存在意义:提高代码的可扩展性,可复用性
,是设计模式的基础。可复用指的是如果不采用多态的方式,相同的代码可能需要使用多份。
上面说了,面向对象是通过访问权限控制,隐藏内部数据,仅提供有限的接口给外部使用。但是普通对象的getter和setter方法滥用,就会导致对象中虽然定义属性是private,但实际上是public的操作权限。若类中存在容器对象,,即使只提供getter方法,也可以修改容器中的数据,推荐做法
为:
public List<ShoppingCartItem> getItems() {
return Collections.unmodifiableList(this.items);
}
一般项目中,会写一个大而全的Constants常量类,明显违背了面向对象设计,存在以下缺点:
推荐做法:尽量做到职责单一,按照业务的不同,划分不同xxxcConstants类
就是经常使用的MVC模式,dao层的实体类和service服务类相分离,即基于贫血模型
的开发方法。
现实中,为了完成一个任务,一般会思考,先做什么,后做什么,如何一步步完成任务,这就是典型的面向过程,适合简单系统开发,例如MVC开发模式。而面向对象是自底向上的逻辑,先构建每个任务的模块,然后思考设计类与类之间的交互,最后按照流程组装
起来完成任务,适合复杂系统的开发。
主要解决的是has-a
问题,降低代码之间的耦合性,将接口和实现相分离,提高代码的扩展性。接口代表自上而下的设计思路。
主要解决的是is-a
问题,提高代码的复用性。抽象类代表自下而上的设计思路。
为什么不直接使用普通类的?原因在于:抽象类的抽象方法强制开发人员必须实现,而普通类则没有要求,那么可能会造成某些方法应该被实现,却没有被实现,不利于代码的可读性,同时无法使用多态特性。
若要表示is-a关系,且为了提高代码的复用性,则使用抽象类;
若要表示has-a关系,且为了提高代码的扩展性,则使用接口。
概述:基于接口而非实现编程,又称```基于抽象而非实现````编程,将接口和实现相分离,隐藏不稳定的实现,暴露稳定的接口实现解耦,增加代码的可扩展性。
实现步骤:
什么场景下使用该原则?
该条原则设计的初衷是面对未来变化场景
。若某个业务场景的实现只有一种方式,就没必要设计接口;否则,就需要设计接口。
思考:
接口的思想:封装隔离
,将调用和创建相互分离。
封装
:通常封装是指对数据的封装,但是这里的封装是指对被隔离体的行为的封装
,或者是
对被隔离体的职责的封装
;
隔离
:隔离指的是外部调用和内部实现
,外部调用只能通过接口进行调用,而外部调用是不知道内部具体实现的,也就是说外部调用和内部实现是被接口隔离开的。
【使用接口的好处】:由于将外部调用和内部实现隔离开来,只要接口定义的行为不变,内部实现
的变化就不会影响到外部系统的调用,使得系统更加灵活,具有更好的扩展性和可维护性,同时具体的实现可以动态切换,而不会影响到系统,即【接口是系统可插拔性的保证】
。例如:
List
,仅是使用了Java的多态语法,使用方即客户端不仅知道接口,还知道具体的实现,是不满足面向接口编程的。解决方案: 简单工厂模式来解决
继承虽然可以提高代码的可复用性,但存在继承层次过深,导致代码难维护的问题。
可以通过组合,接口和委托三个技术手段来解决。适用场景:
例子: A类和B类之间没有继承关系,但是都用到了URL拼接和分割的功能。若为了代码复用,抽出一个父类,会影响代码的可读性,此时使用组合则更加合理,更加灵活。
编写可复用性代码的思考:遵循Rule of Three原则,即第一次写代码不考虑复用性,第二次遇到复用场景时,再考虑重构进行复用。
设计模式的本质就是对某个固定场景的最优解,这个最优解是一套经典模板,并不是所有的场景都适合。目的是为了修改少量代码就可以适应需求的变化
。学习设计模式需要进行如下思考:
- 适用场景
- 优点和缺点。不使用设计模式在面对未来变化时,有哪些不足;使用设计模式在面对未来变化时,有哪些好处
- 满足哪些设计原则
- 稳定点和不稳定点是什么。所谓稳定点指的是不变的点,不稳定点指的是变化的点