面向对象与面向过程、函数式编程

面向对象与面向过程、函数式编程

1. 面向过程编程(Procedure-Oriented Programming)

面向过程编程将程序视为一系列函数的集合,数据和操作数据的函数是分离的。在 Vue 3 中,这种风格通常表现为使用组合式 APIComposition API)以函数式的方式组织代码。

示例:Todo 应用(面向过程)

ts 复制代码
// Todo 应用 - 面向过程实现
import { ref, computed, onMounted } from 'vue';

// 定义数据结构
interface Todo {
  id: number;
  title: string;
  completed: boolean;
}

// 状态管理(使用 ref 和 reactive)
const todos = ref<Todo[]>([]);
const newTodoTitle = ref('');

// 计算属性
const completedTodos = computed(() => 
  todos.value.filter(todo => todo.completed)
);

// 方法
const addTodo = () => {
  if (newTodoTitle.value.trim()) {
    todos.value.push({
      id: Date.now(),
      title: newTodoTitle.value,
      completed: false
    });
    newTodoTitle.value = '';
  }
};

const toggleTodo = (id: number) => {
  const todo = todos.value.find(t => t.id === id);
  if (todo) {
    todo.completed = !todo.completed;
  }
};

const deleteTodo = (id: number) => {
  todos.value = todos.value.filter(t => t.id !== id);
};

// 生命周期钩子
onMounted(() => {
  // 从本地存储加载数据
  const savedTodos = localStorage.getItem('todos');
  if (savedTodos) {
    todos.value = JSON.parse(savedTodos);
  }
});

// 监听变化,保存到本地存储
watch(todos, (newTodos) => {
  localStorage.setItem('todos', JSON.stringify(newTodos));
});

// 导出所有需要在模板中使用的内容
export {
  todos,
  newTodoTitle,
  completedTodos,
  addTodo,
  toggleTodo,
  deleteTodo
};

特点

  • 数据和逻辑分离 :状态(todosnewTodoTitle)和操作(addTodotoggleTodo)是分开定义的。
  • 线性结构:代码按照功能逻辑组织成独立的函数。
  • 灵活组合:可以轻松地复用单个函数或组合多个功能。

2. 面向对象编程(Object-Oriented Programming)

面向对象编程将数据和操作数据的方法封装在一起,形成对象,通过类来创建对象实例。在 Vue 3 中,可以使用类组件或在组合式 API 中封装类来实现。

示例:Todo 应用(面向对象)

ts 复制代码
// Todo 应用 - 面向对象实现
import { ref, computed, onMounted, watch } from 'vue';

// 定义 Todo 类
class Todo {
  constructor(
    public id: number,
    public title: string,
    public completed: boolean = false
  ) {}

  toggle() {
    this.completed = !this.completed;
  }
}

// Todo 管理器类
class TodoManager {
  private _todos = ref<Todo[]>([]);
  private _newTodoTitle = ref('');

  constructor() {
    // 初始化
    onMounted(() => this.loadFromLocalStorage());
    watch(this._todos, () => this.saveToLocalStorage());
  }

  // 获取 todos 的计算属性
  get todos() {
    return this._todos;
  }

  get newTodoTitle() {
    return this._newTodoTitle;
  }

  get completedTodos() {
    return computed(() => 
      this._todos.value.filter(todo => todo.completed)
    );
  }

  // 方法
  addTodo() {
    if (this._newTodoTitle.value.trim()) {
      this._todos.value.push(
        new Todo(Date.now(), this._newTodoTitle.value)
      );
      this._newTodoTitle.value = '';
    }
  }

  toggleTodo(id: number) {
    const todo = this._todos.value.find(t => t.id === id);
    todo?.toggle();
  }

  deleteTodo(id: number) {
    this._todos.value = this._todos.value.filter(t => t.id !== id);
  }

  // 私有方法
  private saveToLocalStorage() {
    localStorage.setItem(
      'todos',
      JSON.stringify(this._todos.value)
    );
  }

  private loadFromLocalStorage() {
    const savedTodos = localStorage.getItem('todos');
    if (savedTodos) {
      this._todos.value = JSON.parse(savedTodos).map(
        (todo: any) => new Todo(todo.id, todo.title, todo.completed)
      );
    }
  }
}

// 创建单例实例
const todoManager = new TodoManager();

// 导出需要在模板中使用的内容
export {
  todoManager
};

特点

  • 封装性:将数据(_todos_newTodoTitle)和操作(addTodotoggleTodo)封装在 TodoManager 类中。
  • 继承与多态:可以通过继承扩展功能(例如创建 AdvancedTodoManager)。
  • 状态内聚:相关的状态和方法被组织在一起,便于维护和复用。
维度 面向过程 面向对象
代码结构 函数和数据分离,线性组织 数据和方法封装在类中,层次化组织
复用方式 函数复用 类的继承和组合
状态管理 分散管理(多个 ref/reactive) 集中管理(类的实例属性)
适用场景 简单逻辑、工具函数、快速迭代 复杂业务逻辑、需要高内聚低耦合的系统
Vue 3 实现方式 组合式 API 类组件或在组合式 API 中封装类

在实际项目中,通常会混合使用两种范式。例如:

  • 使用面向过程的方式处理简单逻辑
  • 使用面向对象的方式封装复杂业务领域模型
ts 复制代码
// 混合使用示例:在组合式 API 中使用类
import { ref, computed, onMounted } from 'vue';

// 定义领域模型(面向对象)
class User {
  constructor(public id: number, public name: string) {}
  
  changeName(newName: string) {
    this.name = newName;
  }
}

// 在组合式 API 中使用(面向过程风格)
export function useUser() {
  const currentUser = ref<User | null>(null);
  
  const fetchUser = async (id: number) => {
    // API 请求...
    const userData = { id, name: 'John' };
    currentUser.value = new User(userData.id, userData.name);
  };
  
  const userName = computed(() => 
    currentUser.value?.name || 'Guest'
  );
  
  return {
    currentUser,
    userName,
    fetchUser
  };
}
  • 面向过程适合简单、灵活的场景,在 Vue 3 中自然地体现为组合式 API 的使用。
  • 面向对象适合复杂、需要高内聚的场景,可以通过类来封装业务逻辑。

3.函数式编程

3.1 对比

编程范式 核心思想 关键特性
面向过程(POP) 将程序分解为一系列步骤(函数),数据与操作分离 函数、顺序执行、共享状态
面向对象(OOP) 将数据和操作封装为对象,通过类创建实例,强调继承和多态 类、对象、继承、封装、多态
函数式编程(FP) 将计算视为函数的求值,避免共享状态和可变数据,强调纯函数和不可变性 纯函数、不可变数据、高阶函数、函数组合、无副作用

3.2 函数式编程与面向过程的关联

3.2.1 相似点
  • 函数为基本单元:两者都使用函数作为代码的基本构建块。
  • 过程式执行:都可以按照步骤顺序执行代码。
3.2.2 不同点
  • 状态管理
    • POP:依赖共享状态和可变数据。
    • FP:避免共享状态,强调不可变性和纯函数。
  • 函数特性
    • POP:函数可以有副作用,修改外部状态。
    • FP:函数是纯的,不产生副作用,相同输入始终返回相同输出。

POP 风格:

ts 复制代码
// 面向过程:使用共享状态和有副作用的函数
const count = ref(0);

const increment = () => {
  count.value++; // 修改共享状态
};

FP 风格:

ts 复制代码
// 函数式:使用不可变数据和纯函数
const state = ref({ count: 0 });

const increment = () => {
  state.value = { ...state.value, count: state.value.count + 1 }; // 创建新对象
};

3.3 函数式编程与面向对象的关联

3.3.1 互补性
  • OOP擅长处理复杂的状态管理和对象关系(如继承、多态)。
  • FP擅长处理数据转换和无副作用的操作。
3.3.2 不同点
  • 封装方式
    • OOP:通过类和对象封装数据和行为。
    • FP:通过函数封装行为,数据和操作分离。
  • 数据流动
    • OOP:通过对象方法修改内部状态(可变数据)。
    • FP:通过纯函数产生新数据(不可变数据)。

OOP 管理领域模型:

ts 复制代码
class ShoppingCart {
  private items = ref<Product[]>([]);
  
  addItem(product: Product) {
    this.items.value = [...this.items.value, product]; // 使用 FP 思想的不可变更新
  }
}

FP 处理数据转换:

ts 复制代码
// 使用纯函数处理数据
const calculateTotal = (items: Product[]) => 
  items.reduce((total, item) => total + item.price, 0);

3.4. 函数式编程在 Vue 3 中的典型应用

3.4.1 纯函数组件
ts 复制代码
// 纯函数组件(无状态)
const Button = (props: { label: string; onClick: () => void }) => {
  return (
    <button onClick={props.onClick}>{props.label}</button>
  );
};
3.4.2 不可变数据处理
ts 复制代码
// 使用 Immer 简化不可变数据操作
import produce from 'immer';

const updateUser = (userId: number, newData: Partial<User>) => {
  users.value = produce(users.value, draft => {
    const user = draft.find(u => u.id === userId);
    if (user) {
      Object.assign(user, newData);
    }
  });
};
3.4.3 高阶函数与组合
ts 复制代码
// 高阶函数:创建可复用的状态处理器
const withLoading = <T>(fetcher: () => Promise<T>) => {
  const loading = ref(false);
  const data = ref<T | null>(null);
  const error = ref<string | null>(null);
  
  const execute = async () => {
    loading.value = true;
    try {
      data.value = await fetcher();
    } catch (err) {
      error.value = err.message;
    } finally {
      loading.value = false;
    }
  };
  
  return { loading, data, error, execute };
};

3.5. 三种范式的协作模式

3.5.1 分层架构
  • 表现层Vue 组件(可以是 OOPPOP 风格)
  • 业务逻辑层 :领域模型(OOP)+ 纯函数(FP
  • 数据访问层 :函数式的数据转换(FP
3.5.2 混合使用示例
ts 复制代码
// 组合式 API 中混合使用三种范式
import { ref, computed } from 'vue';

// OOP:领域模型
class Todo {
  constructor(public id: number, public title: string) {}
  
  markAsCompleted() {
    return new Todo(this.id, this.title, true); // 使用 FP 思想创建新对象
  }
}

// FP:纯函数处理数据
const filterTodos = (todos: Todo[], status: 'all' | 'completed' | 'active') => {
  if (status === 'completed') return todos.filter(t => t.completed);
  if (status === 'active') return todos.filter(t => !t.completed);
  return todos;
};

// POP:组合式 API 组织逻辑
export function useTodos() {
  const todos = ref<Todo[]>([]);
  const filter = ref<'all' | 'completed' | 'active'>('all');
  
  const filteredTodos = computed(() => 
    filterTodos(todos.value, filter.value)
  );
  
  const addTodo = (title: string) => {
    todos.value = [...todos.value, new Todo(Date.now(), title)];
  };
  
  return {
    todos,
    filter,
    filteredTodos,
    addTodo
  };
}
场景 推荐范式 理由
简单脚本或工具函数 面向过程(POP) 快速实现,逻辑直接
复杂业务对象建模 面向对象(OOP) 封装状态和行为,利用继承和多态
数据处理、流式计算 函数式编程(FP) 纯函数和不可变性避免副作用,便于测试和调试
状态管理与组件交互 混合使用 Vue 3 的组合式 API 天然支持多种范式,根据具体需求选择或组合使用
相关推荐
LaoZhangAI23 分钟前
Kiro vs Cursor:2025年AI编程IDE深度对比
前端·后端
止观止26 分钟前
CSS3 粘性定位解析:position sticky
前端·css·css3
爱编程的喵36 分钟前
深入理解JavaScript单例模式:从Storage封装到Modal弹窗的实战应用
前端·javascript
lemon_sjdk1 小时前
Java飞机大战小游戏(升级版)
java·前端·python
G等你下课1 小时前
如何用 useReducer + useContext 构建全局状态管理
前端·react.js
欧阳天羲1 小时前
AI 增强大前端数据加密与隐私保护:技术实现与合规遵
前端·人工智能·状态模式
慧一居士1 小时前
Axios 和Express 区别对比
前端
I'mxx1 小时前
【html常见页面布局】
前端·css·html
快起来别睡了1 小时前
Vuex 与 Pinia:Vue 状态管理详解,小白也能看懂
vue.js