最少知识原则说的是一个软件实体应当尽可能少地与其它实体发生相互作用。这里的软件实体是一个广义的概念,不仅包括对象,还包括系统、类、模块、函数、变量等。
按照这个原则,一个对象应该只调用以下类型的方法:
- 本对象自身的方法。
- 作为方法参数传入的对象的方法。
- 该对象创建或实例化的任何组件的方法。
- 该对象的直接组件的方法。
最少知识原则主张,通过限制对象之间的交互,可以提高系统的可维护性,因为各个组件更加独立,更少受到其他部分的变化的影响。
在实际应用中,这个原则经常被用来指导对象的设计,以减少对象之间的直接引用。这有助于减少系统中的依赖关系,使得每个部分更加独立,从而更容易理解、修改、替换和重构。
最少知识原则在生活中的例子
在日常生活中,最少知识原则的一个例子可能是顾客与咖啡店的互动。当顾客点一杯咖啡时,他们不需要了解咖啡豆的来源、咖啡机的工作原理、或者咖啡师如何管理库存。顾客只需要知道如何点单,支付,以及如何收到他们的咖啡。咖啡店的其他复杂过程对顾客来说是隐藏的,这就减少了顾客需要了解的信息量,简化了他们的决策过程。
在这个例子中,顾客与咖啡店之间的交互被简化到最少的知识和步骤。顾客不需要与咖啡店的每一个内部组件或员工互动,他们只与前台服务员交互,这符合最少知识原则的指导思想。这种互动减少了复杂性,提高了效率,并且使得顾客的体验更加愉快。
最少知识原则在 js 中的应用
在 JavaScript 中,最少知识原则可以应用于减少对象间的直接交互,这样做可以减少对象的依赖性,使得代码更容易维护和扩展。让我们通过一个例子来说明这一点。
假设我们有一个购物车的类,它包含一系列的订单项。如果我们按照最少知识原则,购物车不应该直接了解订单项的内部结构。相反,每个订单项应该提供一个计算自身成本的方法,购物车只需调用这个方法即可。
js
// 订单项类
class OrderItem {
constructor(name, price, quantity) {
this.name = name;
this.price = price;
this.quantity = quantity;
}
// 计算价格的方法
calculateTotal() {
return this.price * this.quantity;
}
}
// 购物车类
class ShoppingCart {
constructor() {
this.items = [];
}
addItem(item) {
this.items.push(item);
}
// 计算购物车总价
calculateTotal() {
return this.items.reduce((total, item) => {
// 使用最少知识原则,只调用 OrderItem 提供的方法
return total + item.calculateTotal();
}, 0);
}
}
// 使用
const cart = new ShoppingCart();
cart.addItem(new OrderItem("Apple", 1.0, 3));
cart.addItem(new OrderItem("Orange", 0.5, 7));
// 购物车不需要知道每个项目的价格和数量是如何计算的
const total = cart.calculateTotal();
console.log(`Total cost: ${total}`);
在这个例子中,OrderItem 的内部结构如价格和数量对于 ShoppingCart 来说是不可见的。ShoppingCart 只知道 OrderItem 有一个 calculateTotal 方法来获取总价。这样,如果 OrderItem 的内部计算逻辑发生变化(比如有折扣或税率变动),只需要在 OrderItem 内部修改 calculateTotal 方法即可,而不需要修改 ShoppingCart 类,这样就实现了解耦。这正是最少知识原则在实际编程中的应用。
最少知识原则在 React 中的应用
在 React 中应用最少知识原则的一个例子可以是父组件通过 props 将信息传递给子组件,而子组件仅使用它们需要展示的数据或执行它们的功能,而不需要知道这些数据来自哪里或者将要如何使用。
这里有一个 React 的例子,其中包含了一个用户列表组件,该组件从其父组件接收用户数据,并渲染出用户的名称。用户列表组件不需要知道用户数据是如何被获取或处理的,它只负责渲染传入的用户数据。
jsx
import React, { useState } from "react";
const UserList = ({ users }) => {
// UserList组件不需要知道用户数据是如何获取或处理的
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
};
const App = () => {
const [users, setUsers] = useState([
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
{ id: 3, name: "Charlie" },
]);
// 这里我们不需要复杂的逻辑来设置用户数据,但如果有,可以使用useEffect Hook
return (
<div>
<h1>User List</h1>
<UserList users={users} />
</div>
);
};
export default App;
在这个例子中,UserInfo 函数组件遵循最少知识原则,它不需要知道 useUserInfo Hook 是如何获取数据的,只需要知道它可以提供所需的用户信息。所有的数据获取和处理逻辑都被隐藏在自定义 Hook useUserInfo 中,使得 UserInfo 组件非常简洁且易于测试和维护。这样的设计提高了组件的可重用性和可维护性。
总结
最少知识原则它鼓励减少对象之间的直接交流。这个原则指导我们设计出相对独立的模块,它们通过简洁的接口相互通信,从而降低了系统的整体复杂性,提高了代码的可维护性和可扩展性。在前端开发中,特别是在使用 React 时,这意味着组件应该只通过 props 接收信息,并尽量不直接与其他组件交互。这样做让组件更加简单、清晰,易于测试和复用。