1、面向过程编程(Procedure Oriented Programming,POP)
- 面向过程(Procedure Oriented):是一种编程范式或编程风格。
- 以步骤为核心,把问题分解成一个个步骤,每个步骤用函数实现,按顺序调用这些函数即可。
- 数据与方法是相互分离的。方法可以操作数据。
- 数据:变量、属性。
- 重点关注"如何一步步实现"。
- 面向过程编程语言最大的特点:
- 不支持类或对象两个语法概念,不支持面向对象编程的特性(如:封装、继承、多态),
- 仅支持面向过程编程。
package org.rainlotus.materials.javabase.a04_oop;
public class ProcessOriented {
static boolean isDoorOpen = false;
static String content = "";
static void openFridge() {
isDoorOpen = true;
System.out.println("打开冰箱门");
}
static void putElephant(String elephant) {
if (isDoorOpen) {
content = elephant;
System.out.println("放入" + elephant);
}
}
static void closeFridge() {
isDoorOpen = false;
System.out.println("关闭冰箱门");
}
public static void main(String[] args) {
openFridge();
putElephant("大象");
closeFridge();
}
}
2、面向对象 (Object Oriented Programming,OOP)
- 面向对象(Object Oriented):是一种编程范式或编程风格。
- 以对象为核心,把问题分解成一个个步骤,对每个步骤进行相应的抽象,形成对象。
- 数据与函数(方法)被封装在类中。通过方法来操作数据。
- 不同对象之间,通过继承、组合实现解决问题。
- 重点关注"谁来做什么",强调抽象、封装、继承、多态,将它们作为代码设计和实现的基石 。
- 面向对象的编程语言:
- 如:Elephant、Fridge 类用面向对象的思想去实现的。
- 但是,main 方法内部的逻辑还是用面向过程的思想去实现的。
package org.rainlotus.materials.javabase.a04_oop;
class Elephant {
private String name;
public Elephant(String name) { this.name = name; }
public String getName() { return name; }
}
class Fridge {
private boolean isDoorOpen;
private Elephant content;
public void openDoor() {
isDoorOpen = true;
System.out.println("打开冰箱门");
}
public void store(Elephant elephant) {
if (isDoorOpen) {
content = elephant;
System.out.println("放入" + elephant.getName());
}
}
public void closeDoor() {
isDoorOpen = false;
System.out.println("关闭冰箱门");
}
}
public class ObjectOriented {
public static void main(String[] args) {
Fridge fridge = new Fridge();
Elephant elephant = new Elephant("大象");
fridge.openDoor();
fridge.store(elephant);
fridge.closeDoor();
}
}
3、函数式编程(Functional Programming,FP)
- 函数式编程:是一种抽象程度很高的声明式编程范式。
- 核心思想:
- 将计算看做是数学函数的求值。
- 强调通过组合纯函数、避免可变状态和副作用来构建程序。
- 函数式编程中“函数”的含义:
- 数学函数:输入到输出的映射,无副作用,行为可预测。
- 一等公民(First-Class Citizen):函数可以像变量一样被传递、返回和存储。
- 允许把函数本身作为参数传入另一个函数,还允许返回一个函数。
- 函数式编程的优势:
- 可维护性:无副作用和不可变性减少隐藏的 Bug。
- 可测试性:纯函数易于单元测试。
- 并发安全:不可变数据天然线程安全。
- 函数式编程通过纯函数、不可变数据和高阶函数,提供了一种更安全、更简洁的代码组织方式。
- Java 虽然并非纯函数式语言,但通过 Lambda 和 Stream API 支持函数式风格。
- 使开发者能够结合面向对象与函数式编程的优势。
1、核心特征 1 – 纯函数(Pure Function)
- 给定相同输入,总是返回相同输出。
- 无副作用(不修改外部状态。如:没有全局变量、IO 操作等)。
public static int add(int a, int b) {
return a + b;
}
2、核心特征 2 – 不可变性(Immutability)
- 数据一旦创建,不可被修改,任何“修改”操作都生成新数据。
public final class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
3、核心特征 3 – 高阶函数(Higher-Order Function)
public static List<Integer> processNumbers(
List<Integer> numbers,
Function<Integer, Integer> processor
) {
return numbers.stream()
.map(processor)
.collect(Collectors.toList());
}
List<Integer> numbers = Arrays.asList(1, 2, 3);
List<Integer> doubled = processNumbers(numbers, n -> n * 2);
4、核心特征 4 – 声明式风格(Declarative Style)
- 关注“做什么”而非“如何做”。如:用 filter、map 代替 循环。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * n)
.reduce(0, Integer::sum);
System.out.println(sum);
4、面向对象编程 相比 面向过程编程 的优势
- 对于大规模复杂程序的开发,程序的处理流程并非单一的一条主线,而是错综复杂的网状结构。
- 面向对象编程比起面向过程编程,更能应对这种复杂类型的程序开发。
- 面向对象编程相比面向过程编程,具有更加丰富的特性(封装、抽象、继承、多态)。
- 利用这些特性编写出来的代码,更加易扩展、易复用、易维护。
- 从编程语言跟机器打交道的方式的演进规律中,可以总结出:
- 面向对象编程语言比起面向过程编程语言,更加人性化、更加高级、更加智能。
5、Java 中常见的面向过程风格的代码
1、滥用 getter、setter 方法
- 一个类,无论是否需要,为所有属性都提供了 get / set 方法。
2、滥用全局变量和全局方法
- 常见的一个项目一个大而全的 Constants 类,一个大而全的 Utils 类。
- 如何避免?
- 1、针对不同的功能,设计不同的 Constants 类、 Utils 类。
- 如:FileConstants、MysqlConstants 等,FileUtils、StringUtils 等。
- 2、不单独地设计 Constants 常量类,把具体类用到的常量封装定义在该类内部 。
- 如:RedisConfig 类用到了 Redis 配置相关的常量 ,就直接定义在 RedisConfig 中。
- 提高了类设计的内聚性和代码的复用性 。
3、定义数据和方法分离的类 – 基于贫血模式的开发模式
- 后端开发常见的分层模型:
- Controller 层负责暴露接口给前端调用、Service 层负责核心业务逻辑,Repository 层负责数据读写 。
- 在每一层中,又会定义相应的 VO(View Object)、BO(Business Object)、Entity。
- 一般情况下,VO、BO、Entity 中只会定义数据,不会定义数据的操作方法。
- 所有操作这些数据的业务逻辑都定义在对应的 Controller 类、Service 类、Repository 类中。
- 这就是典型的面向过程的编程风格 。