不知道你有沒有在某處見過 xxProvider,Provider 並非 23 種經典設計模式之一,可是卻應用特別多,能夠算是一種比較新的模式。react
還有不少別的地方也常常會見到 Provider 的概念,那麼 Provider 到底是什麼呢?typescript
本文就來回答下這幾個問題:設計模式
provider 是提供者,從名字上和設計模式中建立對象的那些模式很像,好比工廠方法模式,但其實二者是有區別的。api
工廠方法模式是用於建立不一樣的產品,經過繼承的方式。markdown
但有的時候建立的對象可能有別的來源,好比從別的地方獲取的一個值,或者已經建立好的對象。這時候來源就不僅有工廠了。angular2
也就是說這時候要建立的對象有多種策略,工廠只是其中一種,策略 + 工廠/其餘方式就是 Provider。架構
provider 被微軟引入到了 .net 2.0,並且微軟其餘的一些技術產品也隨處能夠見 provider,好比 VSCode 的 xxxProvider、angular2 的 providers。框架
咱們來看一些具體的應用。ide
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 的方式。
父組件的做爲 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 的思想。
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 呢?能夠留言交流哦~