定义
“软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。”
这意味着我们应该能够添加新的功能或行为,而无需修改现有的代码。
对扩展开放 =>
允许通过拓展来添加新功能或行为
对修改关闭 =>
不直接修改现有代码
分析
对应到react
中,首选的场景就是组件了。react
的组件的props
其实就是开闭原则的一个很好的例子。因为我们可以通过props
添加新增行为而无需修改现有代码。
反例
下面这个组件在初期应该能工作良好,但当我们需要添加新的按钮类型时,就不得不进入组件内部进行修改,这简单直接的违反了开闭原则。
function Button(props) {
const { type } = props;
let icon = null;
if (type === 'face') {
icon = <FaceIcon />;
}
if (type === 'star') {
icon = <StarIcon />;
}
if (type === 'like') {
icon = <LikeIcon />;
}
return <button>{icon}Click me</button>;
}
function App() {
return (
<>
<Button type="face" />
<Button type="star" />
<Button type="like" />
</>
);
}
正例
在下面的代码中,我们通过传入icon
为组件添加了新的行为,并且没有修改现有的组件代码。
function Button(props) {
const { icon } = props;
return <button>{icon}Click me</button>;
}
function App() {
return (
<>
<Button icon={<FaceIcon />} />
<Button icon={<StarIcon />} />
<Button icon={<LikeIcon />} />
</>
);
}
我们甚至可以更进一步,将icon
重命名为prefix
,这样就不仅限于icon
,我们可以传递各种类型来实现我们想要的需求,让组件具有更高的灵活性。(react
中的props.children
也是这个道理)
function Button(props) {
const { prefix } = props;
return <button>{prefix}Click me</button>;
}
function App() {
return (
<>
<Button prefix={<FaceIcon />} />
<Button prefix={<StarIcon />} />
<Button prefix={<LikeIcon />} />
</>
);
}
结论
通过上面的组件代码,我们可以发现应用了开闭原则的版本有以下优点:
降低风险:
直接修改现有代码可能会引入错误,导致组件不稳定。而通过扩展而不是修改,我们可以减少这种风险。
易于维护:
可以更容易地维护代码,当我们需要添加新功能时,我们只需关注新增的部分,而不必担心影响其他地方。这也有助于降低维护成本。
灵活性:
通过对扩展开放,我们可以在不修改现有代码的情况下引入新功能。这使得我们的组件更加灵活,能够适应不断变化的需求。