Leen27 / Diary

技术日记
0 stars 0 forks source link

[设计模式] 控制反转 #15

Open Leen27 opened 1 year ago

Leen27 commented 1 year ago
Leen27 commented 1 year ago

一个函数或者组件,我们只需要抽象出一个单一职责的接口,具体实现方式抛出给用户去实现

Leen27 commented 1 year ago

未使用控制反转

在需要新功能时,必须添加新的 options,并且代码里也要添加 if,添加新功能代码...

// let's pretend that Array.prototype.filter does not exist
function filter(
  array,
  {
    filterNull = true,
    filterUndefined = true,
    filterZero = false,
    filterEmptyString = false,
  } = {},
) {
  let newArray = []
  for (let index = 0; index < array.length; index++) {
    const element = array[index]
    if (
      (filterNull && element === null) ||
      (filterUndefined && element === undefined) ||
      (filterZero && element === 0) ||
      (filterEmptyString && element === '')
    ) {
      continue
    }

    newArray[newArray.length] = element
  }
  return newArray
}

filter([0, 1, undefined, 2, null, 3, 'four', ''])
// [0, 1, 2, 3, 'four', '']

filter([0, 1, undefined, 2, null, 3, 'four', ''], {filterNull: false})
// [0, 1, 2, null, 3, 'four', '']

filter([0, 1, undefined, 2, null, 3, 'four', ''], {filterUndefined: false})
// [0, 1, 2, undefined, 3, 'four', '']

filter([0, 1, undefined, 2, null, 3, 'four', ''], {filterZero: true})
// [1, 2, 3, 'four', '']

filter([0, 1, undefined, 2, null, 3, 'four', ''], {filterEmptyString: true})
// [0, 1, 2, 3, 'four']

使用控制反转

控制权交给了用户,函数代码简单了许多,缺点是用户代码会多出来

// let's pretend that Array.prototype.filter does not exist
function filter(array, filterFn) {
  let newArray = []
  for (let index = 0; index < array.length; index++) {
    const element = array[index]
    if (filterFn(element)) {
      newArray[newArray.length] = element
    }
  }
  return newArray
}

filter(
  [0, 1, undefined, 2, null, 3, 'four', ''],
  el => el !== null && el !== undefined,
)
// [0, 1, 2, 3, 'four', '']

filter([0, 1, undefined, 2, null, 3, 'four', ''], el => el !== undefined)
// [0, 1, 2, null, 3, 'four', '']

filter([0, 1, undefined, 2, null, 3, 'four', ''], el => el !== null)
// [0, 1, 2, undefined, 3, 'four', '']

filter(
  [0, 1, undefined, 2, null, 3, 'four', ''],
  el => el !== undefined && el !== null && el !== 0,
)
// [1, 2, 3, 'four', '']

filter(
  [0, 1, undefined, 2, null, 3, 'four', ''],
  el => el !== undefined && el !== null && el !== '',
)
// [0, 1, 2, 3, 'four']

进阶

我们可以在抽象出的函数基础上,在封装特定的功能代码,减少用户使用的代码量

function filterByLegCount(array, legCount) {
  return filter(array, animal => animal.legs === legCount)
}

filterByLegCount(
  [
    {name: 'dog', legs: 4, mammal: true},
    {name: 'dolphin', legs: 0, mammal: true},
    {name: 'eagle', legs: 2, mammal: false},
    {name: 'elephant', legs: 4, mammal: true},
    {name: 'robin', legs: 2, mammal: false},
    {name: 'cat', legs: 4, mammal: true},
    {name: 'salmon', legs: 0, mammal: false},
  ],
  0,
)
// [
//   {name: 'dolphin', legs: 0, mammal: true},
//   {name: 'salmon', legs: 0, mammal: false},
// ]
Leen27 commented 1 year ago

JSX 代码

function App() {
  return (
    <Menu
      buttonContents={
        <>
          Actions <span aria-hidden>▾</span>
        </>
      }
      items={[
        {contents: 'Download', onSelect: () => alert('Download')},
        {contents: 'Create a Copy', onSelect: () => alert('Create a Copy')},
        {contents: 'Delete', onSelect: () => alert('Delete')},
      ]}
    />
  )
}

控制反转后

function App() {
  return (
    <Menu
      buttonContents={
        <>
          Actions <span aria-hidden>▾</span>
        </>
      }
      items={[
        {contents: 'Download', onSelect: () => alert('Download')},
        {contents: 'Create a Copy', onSelect: () => alert('Create a Copy')},
        {contents: 'Delete', onSelect: () => alert('Delete')},
      ]}
    />
  )
}