先粘贴来自知乎上的一个原问题:
为什么前端开发中感受不到依赖倒置原则的应用?
几乎无论用什么后端框架,都逃避不了依赖倒置这个首要问题。比如做得好的框架,都内置了依赖倒置的支持,无论 Nest js,inversify js,还要 java spring 系列,还是微软 dotnet core。
但前端框架像 react,vue ,都感受不到依赖倒置的存在呢?
唯独 angular 比较特别,有依赖倒置的支持并且直接启发了 Nest js 的开发。
但问题是,为什么前端开发中大多数情况下,感受不到依赖倒置原则的应用?
感受不到是真的吗?
答案很肯定:是的
那原因是什么呢?首先,你得了解一下什么是设计模式 。按我自己的理解来解释的话:设计模式是前人在使用面向对象范式进行开发时,应对软件的变化,总结的一些经验和原则。
提取关键词:
面向对象
那实际上前端在开发中,接触到最多的是什么?JS,HTML,css。
1.这三者中有两个跟面向对象没有关系
2.唯一跟面向对象沾边的JS,在实际开发中,我们很少使用它的class语法。所以一点也不面向对象
这两个客观因素导致前端很难感受到依赖倒置原则在前端中的应用。
变化
其实到我们前端开发的时候,基本上应对的都是业务末端,也就意味着全是变化。而面向对象的目的是求同存异,降低变化带来的影响。如果你面对的全部都是不同,你怎么会去想着封装呢?那你怎么又会想起设计模式呢?
其实在以前,前端是有很多机会去体会到设计模式的应用的:比如封装一个组件库;又或者封装一个框架、一个工具库。
但是现在,开源社区已经把这个事情都做完了。所以前端每天的工作都是专注在业务上面了,自然也就没有应用到设计模式了
但是,前端就不存在依赖倒置的应用吗?
答案是否定的,前端中几乎每天都在使用这个原则
我举个两个栗子:
1。按钮的事件监听
2。vue的插槽slot
3。react中的 render props 前端的小伙伴们,你们是不是天天在用呢?现在我以第二个例子来解释
xml
<!-- 筛选容器组件 -->
<div name="container">
<Daterange-picker />
<slot />
<button onClick="fliterCompletion" >
完成
</button>
</div>
<!-- 在页面A中调用 -->
<div>
<container onFilterCompletion="yourMethod">
<input filed="name" />
</container>
</div>
<!-- 在页面B中调用 -->
<div>
<container onFilterCompletion="yourMethod">
<input filed="age" />
</container>
</div>
上面这样是不是做到了,依赖倒置的两大内容?
1。高层模块不应该依赖于低层模块。两者都应该依赖于抽象。
高层-> 页面
低层->时间范围组件
抽象->筛选容器组件(包含了时间范围组件)
业务需求:
页面上想要实现一个筛选功能,固定的条件有日期范围,其他别的使用地方可能需要一个年龄的input,又或者是性别、姓名的input。
如果在每个页面单独写,你就要写很多个,费时费力。
如果全部写在同一个筛选容器组件里面,你就会写很多if else,违反了单一职责的原则。
改造之后,你可以根据页面上的需要,往容器里面添加筛选条件。但是又不必直接将代码写在筛选组件中。这就实现了:高层模块不应该依赖于低层模块。两者都应该依赖于抽象
2。抽象不应该依赖于具体实现。具体实现应该依赖于抽象
这个地方这样解释:
你在不同的页面中都会使用筛选的功能,但是在A页面,筛选完成后,你去调的是接口"甲",在B页面你去调的是接口"乙"。虽然都要在筛选完成后调用接口,但是具体的页面调用的接口是不同的
这个时候抽象就是 "filterCompletion ",
具体就是 "yourMethod",你想如何实现你自己的业务
也是就是具体的业务实现依赖于抽象的接口。
我上面这种业务需求,是否符合"多数情况"? ###总结### 1.前端开发确实很难感受到依赖倒置的原则,原因有两点,一是使用的语言不是面向对象的;二是,在最容易感受到的JS应用上,我们没有去使用它的面向对象范式
2.前端开发中,很多不变已经被开源社区给封装起来了,例如UI组件库,框架,工具库,脚手架等。每天都是在面对业务做文章。很难主动感受到
3.通过对业务的抽象,我们依然能够感受到设计模式在前端中的应用。希望大家在专注业务的同时,增加思考。这样就能收获进步的喜悦!!