背景
在大型和复杂的业务中,我们会将逻辑拆分成多个服务用来处理不同的业务场景。子服务需要使用同一份数据或公共方法等,用JS继承是比较好的方式。
JS实现继承的方式有很多种,原型链继承、构造函数继承,组合继承,原型式继承,寄生式继承,寄生组合式继承,ES6 Class 语法。
下面介绍一下使用“原型式继承”实现业务拆分不同子服务实现。
原型式继承Demo:
通过 Object.create 方法创建一个新的对象,该对象的原型指向父对象。
const parent = {
name: 'parent',
sayHello: function() {
console.log('Hello from ' + this.name);
}
};
const child = Object.create(parent);
child.name = 'child';
child.sayHello(); // 输出:Hello from child
1. 定义function
首先,我们需要定义一个 function 用于接收数据
// previewService.js
import AllocationService from './allocation'
import AdSubmitService from './ad-submit'
import BatchEditService from './batch-edit'
import HelperService from './helper'
export default function (
bluePrint,
bluePrintConfig,
bluePrintService,
getCurAccountListFn,
campaignSnInfo,
adSnInfo,
creativeSnInfo
) {
// ...
}
2. 实现原型父对象
实现一个自定义函数,定义原型父对象并添加新数据
function helperParent(
bluePrint,
bluePrintConfig,
bluePrintService,
getCurAccountListFn,
campaignSnInfo,
adSnInfo,
creativeSnInfo
) {
// 1. 定义原型父对象
const parent = {
bluePrint,
bluePrintConfig,
bluePrintService,
getCurAccountListFn,
campaignSnInfo,
adSnInfo,
creativeSnInfo
}
// 2.通过 `Object.create` 方法创建一个新的对象,该对象的原型指向父对象。
const helper = Object.create(parent)
for (let key in HelperService) {
helper[key] = HelperService[key]
}
// 3. 添加新公共数据
parent.curModuleVars = helper.defineCurModuleVars()
return parent
}
3. 添加子服务对象原型指向原型父对象
现在,我们可以在 添加任意的子服务了
最后renturn 所有子服务
export default function(//...//) {
// 获取原型对象
const helpParent = helperParent(//...//)
// 添加子服务
const allocation = Object.create(helpParent)
for (let key in AllocationService) {
allocation[key] = AllocationService[key]
}
return Object.assign(parent, {allocation} )
}
这样AllocationService中可以使用helpParent中的所有数据。
// allocation.js
const allocation = {
initMediaAccountList(adResult) {
// 使用原型数据
if(this.bluePrint){
// ...
}
}
}
export default allocation
使用
// 1. 传入数据
this.curPreviewService = new PreviewService(
this.myBluePrint,
this.bluePrintConfig,
this.bluePrintService,
this.getCurAccountListFn,
this.campaignSnInfo,
this.adSnInfo,
this.creativeSnInfo
)
// 2. 使用子服务
const accountList = this.curPreviewService.allocation.initMediaAccountList(adResult)
完整代码
import AllocationService from './allocation'
import AdSubmitService from './ad-submit'
import BatchEditService from './batch-edit'
import HelperService from './helper'
function helperParent(
bluePrint,
bluePrintConfig,
bluePrintService,
getCurAccountListFn,
campaignSnInfo,
adSnInfo,
creativeSnInfo
) {
//
const parent = {
bluePrint,
bluePrintConfig,
bluePrintService,
getCurAccountListFn,
campaignSnInfo,
adSnInfo,
creativeSnInfo
}
const helper = Object.create(parent)
for (let key in HelperService) {
helper[key] = HelperService[key]
}
parent.curModuleVars = helper.defineCurModuleVars()
return parent
}
export default function (
bluePrint,
bluePrintConfig,
bluePrintService,
getCurAccountListFn,
campaignSnInfo,
adSnInfo,
creativeSnInfo
) {
// 所有子类共享的变量(数据唯一出口)
const parent = helperParent(
bluePrint,
bluePrintConfig,
bluePrintService,
getCurAccountListFn,
campaignSnInfo,
adSnInfo,
creativeSnInfo
)
let serviceObject = {
allocation: AllocationService,
adSubmit: AdSubmitService,
batchEdit: BatchEditService
}
let service = {}
for (let name in serviceObject) {
service[name] = Object.create(parent)
for (let key in serviceObject[name]) {
service[name][key] = serviceObject[name][key]
}
}
// 子服务组合
const serviceGroup = {
// 批量操作回调
handleBatchEditOk({ data, editConfig, tbody, tbodyIds }) {
const AllocationService = service.allocation
service.batchEdit.handleChangeCallback({
data,
editConfig,
AllocationService,
tbody,
tbodyIds
})
}
}
return Object.assign(parent, { ...service }, { ...serviceGroup })
}
结论
通过上述示例,实现不同子服务共用数据能力
ps:历史代码升级,入参数据可以简化。