前端代碼常常見到的 Provider 是什麼

不知道你有沒有在某處見過 xxProvider,Provider 並非 23 種經典設計模式之一,可是卻應用特別多,能夠算是一種比較新的模式。react

  • Angular2 中提供了建立對象的時候基於 Provider
  • VSCode 插件中有各類 registerXxxProvider 的 api
  • React 提供了 Provider 組件用於 context 數據的傳遞

還有不少別的地方也常常會見到 Provider 的概念,那麼 Provider 到底是什麼呢?typescript

本文就來回答下這幾個問題:設計模式

  • provider 是什麼
  • provider 建立對象和 factory 有什麼區別
  • provider 的具體應用

provider 是什麼

provider 是提供者,從名字上和設計模式中建立對象的那些模式很像,好比工廠方法模式,但其實二者是有區別的。api

工廠方法模式是用於建立不一樣的產品,經過繼承的方式。markdown

但有的時候建立的對象可能有別的來源,好比從別的地方獲取的一個值,或者已經建立好的對象。這時候來源就不僅有工廠了。angular2

也就是說這時候要建立的對象有多種策略,工廠只是其中一種,策略 + 工廠/其餘方式就是 Provider。架構

provider 被微軟引入到了 .net 2.0,並且微軟其餘的一些技術產品也隨處能夠見 provider,好比 VSCode 的 xxxProvider、angular2 的 providers。框架

咱們來看一些具體的應用。ide

provider 的具體應用

VSCode 插件的 provider 系列 api

VSCode 插件中最多見的 api 就是 registerXxxProvider,經過該 api 註冊的 Provider 就是實現了 provideXxx 的對象。函數

好比智能補全就是註冊一個 CompletionProvider,而後根據 document 的內容,返回具體的 CompletionItem 的對象。

由於 VSCode 並不關心 CompletionItem 是怎麼建立出來的,只知道經過這個 provider 能夠拿到須要的 completion 數據,因此設計了 provider 的 api。

const provider = vscode.languages.registerCompletionItemProvider(
        'plaintext',
        {
                provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) {
                        return [
                                new vscode.CompletionItem('log', vscode.CompletionItemKind.Method),
                                new vscode.CompletionItem('warn', vscode.CompletionItemKind.Method),
                                new vscode.CompletionItem('error', vscode.CompletionItemKind.Method),
                        ];
                }
        },
        '.'
);

context.subscriptions.push(provider);
複製代碼

React 中的 context 的 Provider

react 組件樹能夠在父組件放一些數據到 context 中,而後子組件取出來用,也是經過 provider 的方式。

父組件的做爲 Provider 須要實現 getChildContext 方法,返回具體的對象。就像上面的 provideXxx 同樣,react 並不關心這個對象是怎麼來的。

父組件裏提供 getChildContext 提供數據

class Ancestor extends React.Component {
  getChildContext() {
    return { value1: "context1", value2: "context2" };
  }
  render() {
    return <Parent />;
  }
}

class Parent extends React.Component {
  render() {
    return <Child />
  }
}
複製代碼

子組件裏拿出來

class Child extends React.Component {
  render() {
    console.log(this.context.value1);
  }
}
複製代碼

固然,react 對上面的流程進行了封裝,提供了 React.createContext 的 api 和 Provider、Consumer 組件。

const Context = React.createContext();

class Child extends React.Component {
  render() {
    return (
      <Context.Consumer> {({ value1 }) => { console.log(value1); }} </Context.Consumer>
    );
  }
}

class Parent extends React.Component {
  render() {
    return <Child />
  }
}

class Ancestor extends React.Component {
  render() {
    return (
      <Context.Provider value={{ value1: "context1" }}> <Parent /> </Context.Provider>
    );
  }
}
複製代碼

這裏也是 provider 的思想。

Angular2 的 providers

angular 最大的特色就是實現了 ioc,也就是在容器內的對象,能夠聲明依賴對象,而後用到的時候會自動注入。這個對象的建立方式也是 provider 的形式。

咱們知道,provider 並不關心具體對象是怎麼建立的,能夠動態切換多種建立策略,而 angular2 就提供了 4種策略: Class、Factory、Value、Exsiting

直接值:

@NgModule({
  providers: [
       { provide: 'ggg', useValue: 'guang' }
  ]
})
export class MainModule { }
複製代碼

已有的:

@NgModule({
  providers: [
      { provide: 'ggg', useExisting: Guang }
  ]
})
export class MainModule { }
複製代碼

類:

@Injectable()
export class Guang {
   constructor(public name: string) {
   }
}
@NgModule({
  providers: [
       { provide: 'ggg', useClass: Guang}
  ]
})
export class MainModule { }
複製代碼

工廠:

function guangFactory() {
  return () => { name: 'guang' };
}

@NgModule({
  providers: [
       { provide: 'ggg', useFacotry: guangFactory }
  ]
})
export class MainModule { }
複製代碼

能夠看到,angular 提供的 provider 具體的建立策略有好多種,工廠只是其中一種方式,這是 provider 和工廠的區別。

總結

provider 是一種建立對象的模式,可是和工廠不一樣,它是有不一樣的建立策略的,算是一種複合模式,工廠只是其中一種策略,這種模式在 Angular 的 ioc 建立對象的時候、VSCode 插件註冊各類處理函數的時候都有大量應用,還有 React 也基於 Provider 作 context 的傳遞。

Provider 是各類框架中頻繁出現的一個概念,掌握 provider 的思想,對於理解框架還有咱們設計代碼架構都會有幫助。但願本文可以幫你們理解 Provider。

你們還有沒有在別的地方見過 Provider 呢?能夠留言交流哦~

相關文章
相關標籤/搜索