概述
POP:面向过程编程(Procedure Oriented Programming)
OOP:面向对象编程(Object Oriented Programming)
AOP:面向切面编程(Aspect Oriented Programming)
FOP:面向函数式编程(Functional Oriented Programming)
POP
POP :面向过程编程(Procedure Oriented Programming):这种编程方式以功能为中心,强调通过过程(函数)来组织代码 。它适合于流程化编程
,但在代码重用性方面较低
- 常见的语言有
C、Pasca
l等。 - 采用
函数作为程序的基本单元
,通过函数之间的调用来实现程序的功能
。 - 优点:
- 相对
简单和直观
,易于理解和实现。 - 对于简单的问题和小规模程序,
面向过程编程具有高效性和执行速度优势
。 更加灵活
,可以通过过程的组合和调用来构建更复杂的功能。
- 相对
- 缺点:
- 缺乏模块化和封装性,
难以重用和维护
。 - 难以应对复杂的问题和大规模的软件开发。
- 容易造成
代码冗余和可扩展性差
。
- 缺乏模块化和封装性,
- 例子:将大象装入冰箱步骤: 打开冰箱门 ==》将大象放进冰箱 ==》关闭冰箱门。
OOP
OOP:面向对象 编程(Object Oriented Programming):强调将数据和操作数据的函数封装在一起,形成对象
。通过类和对象的概念,程序员可以更好地组织代码,提高代码的重用性和可维护性。
- 常见的语言有
Java、C++、Python
等。 以对象为中心
,强调封装、继承和多态,面向对象编程强调将问题抽象成对象,并通过对象之间的交互来解决问题。抽象包括两个方面:过程抽象和数据抽象
- 过程抽象:把一个系统
按功能划分
成若干个子系统,进行自顶向下逐步求精的程序设计。 - 数据抽象:以
数据为中心,将数据对象、数据对象之间的关系和数据对象的基本操作封装
在一起(对象)来进行描述,形成抽象数据类型ADT(Abstract Data Type)
- 过程抽象:把一个系统
封装
:用户只能看见对象封装界面上的信息,对象的内部实现对用户是隐蔽的
。继承
:类间的基本关系
,它是基于层次关系的不同类共享数据和操作的一种机制多态
:一个类实例的相同方法在不同的情形有不同的表现形式
- 使具有不同内部结构的对象可以共享相同的外部接口,实现了,
通过一个公共类可以以相同的方式调用不同对象的不同实现
。 - 实现:
重写overwrite(运行时决定)、重载overload(编译时决定)
- 使具有不同内部结构的对象可以共享相同的外部接口,实现了,
- 这种思想使得
代码更易于扩展和维护,但可能导致较高的耦合度
。 - 优点:
- 提供了更高层次的抽象和封装,使代码
更易于理解和维护
。 - 支持代码的重用和模块化,提高开发效率。
- 通过继承和多态性实现代码的灵活性和可扩展性。
- 提供了更高层次的抽象和封装,使代码
- 缺点:
- 学习曲线较陡峭,需要掌握面向对象的概念和设计原则。
- 对于小规模和简单问题,面向对象可能带来不必要的复杂性。
- 在某些情况下,面向对象的开销较大,执行效率可能不如面向过程。
- 例子:将大象装入冰箱步骤: 创建一个冰箱对象 ==》创建一个大象对象 ==》冰箱对象调用打开门的方法 ==》大象对象调用进入冰箱的方法 ==》冰箱对象调用关闭门的方法
AOP(OOP的补充)
AOP:面向切面编程
(Aspect Oriented Programming):AOP关注于切面,旨在降低模块之间的耦合度,简化系统的维护。它通过将横切关注点(如日志、事务等)从业务逻辑中分离出来,提高了代码的可维护性。
- 在应用程序中多个模块共同需要的功能,例如日志记录、事务管理等。
- 通过将这些关注点从核心业务逻辑中分离出来,使得代码更加模块化和可维护。
- 优点:
- 提高了代码的可重用性和可维护性。
- 实现了关注点的集中管理,使得业务逻辑更加清晰和简洁。
- 降低了模块之间的耦合度,提高了系统的灵活性和可扩展性。
- 缺点:
- 引入了额外的复杂性和学习成本。
- 可能导致系统的运行时性能损失。
- 例子:将大象装入冰箱步骤: 创建一个日志记录的切面 ==》将日志记录切面应用到打开门的操作中 ==》将日志记录切面应用到关闭门的操作中 ==》创建一个冰箱对象 ==》创建一个大象对象 ==》冰箱对象调用打开门的方法,切面会记录日志 ==》大象对象调用进入冰箱的方法 ==》冰箱对象调用关闭门的方法,切面会记录日志
FOP
函数式编程
(Functional Programming):函数式编程强调使用纯函数和不可变数据
。它关注于计算的结果而不是计算的过程
,鼓励使用高阶函数和递归。常见的语言有Haskell、Scala、JavaScript等。
- 也是一种
以函数为基本单位的编程思想,将程序看作是一系列函数的组合
,通过对函数的调用和组合来实现程序的功能。函数式编程的核心是函数的定义和函数的调用
- 和POP的区别:
- 函数是一种无状态的、不可变的计算单元,接受输入参数并返回结果
无状态:函数内部涉及的变量都是局部变量
函数执行的结果只和入参有关,与其他外部变量无关
,同样的入参,无论如何执行,得到的结果都是一样的- 实际上:就是数学函数或者数学表达式的基本要求
- 函数是一种无状态的、不可变的计算单元,接受输入参数并返回结果
oop 五大设计原则
单一职责原则 (Single-Resposibility Principle):单一职责有2个含义,一个是避免相同的职责分散到不同的类中
,另一个是避免一个类承担太多职责
。减少类的耦合度,提高类的复用性
- 如果一个类承担的职责过多,那么这些职责就会相互依赖,一个职责的变化可能会影响另一个职责的履行。其实
面向对象设计(OOD)的实质,就是合理地进行类的职责分配
。 一个类或模块只负责完成一个职责
接口隔离原则 (Interface-Segregation Principle):表明客户端不应该被强迫实现一些他们不会使用的接口
,应该把胖接口中的方法分组,然后用多个接口代替它,每个接口服务于一个子模块
接口的调用者不应该被强迫依赖它不需要的接口
- 当某个客户程序的要求发生变化,而迫使接口发生改变时,影响到其他客户程序的可能性小。
开放-封闭原则(Open-Closed principle):一个模块在扩展性方面应该是开放的而在更改性方面应该是封闭的。
对扩展性开放,对修改关闭
- open模块的行为必须是开放的、支持扩展的,而不是僵化的
- closed在对模块的功能进行扩展时,不应该影响或大规模影响已有的程序模块。
核心思想就是对抽象编程,而不对具体编程
- 如果说我们预测到某种变化,或者某种变化发生了,我们应当创建抽象类来隔离以后发生的同类变化。
在Java中,这种抽象是指抽象基类或接口
替换原则(Liskov-Substitution Principle):子类型必须能够替换掉他们的父类型、并出现在父类能够出现的任何地方
子类对象能够替换父类对象出现的任何地方,并且要保证原来的程序逻辑行为和正确性不被破坏
主要针对继承的设计原则
- 在客户端程序中只应该使用父类对象而不应当直接使用子类对象,这样可以实现运行期间绑定。
本原则和开放封闭原则关系密切
,正是子类型的可替换性,才使得使用基类型模块无需修改就可扩充
依赖倒置原则 (Dependecy-Inversion Principle):上层模块不应该依赖于下层模块,他们共同依赖于一个抽象(父类不能依赖子类,他们都要一类抽象类
),抽象不能依赖于具体,具体应该要依赖于抽象
高层模块不用了底层模块
,二者应该通过抽象来互相依赖;抽象不依赖具体实现细节
,具体实现细节依赖抽象
- 人解决问题的思考过程是
先抽象后具体,从笼统到细节,所以我们先生产出的势必是抽象程度比较高的实体,而后才是更加细节化的实体
,依赖倒置原则适应了人类认识过程的规律,是面向对象设计的标志所在
。 - 抽象的实体代表着笼而统之的认识,人们总是比较容易正确认识它们,而且本身也是不易变的,依赖于它们是安全的。
补充:良性依赖原则
。"不会在实际中造成危害的依赖关系,都是良性依赖。"通过分析不难发现,本原则的核心思想是"务实",很好地揭示了极限编程(Extreme Programming)中"简单设计"各"重构"的理论基础。本原则可以帮助我们抵御"面向对象设计五大原则"以及设计模式的诱惑,以免陷入过度设计(Over-engineering)的尴尬境地,带来不必要的复杂性