程序中經(jīng)常會(huì)用到很多不同的設(shè)計(jì)模式, 而工廠模式的使用率, 是設(shè)計(jì)模式中使用率比較高的.
當(dāng)我們用工廠模式的時(shí)候, 需要寫一個(gè)Factory來(lái)創(chuàng)建各個(gè)類
interface IObjConstructor {
new <T>() : T;
}
function create(c : IObjConstructor) : C1 {
return new c()
}
代碼里的create就是我們要的factory了, 然后我們寫一個(gè)class實(shí)現(xiàn)IObjConstructor接口.
class C1 implements IObjConstructor {
constructor() {
}
}
這段代碼看上去很正常, C1類實(shí)現(xiàn)了接口IObjConstructor, 但是編譯會(huì)報(bào)錯(cuò)
Type 'C1' provides no match for the signature 'new <T>(): T'
奇怪了, 為什么說(shuō)C1沒(méi)有這個(gè)new屬性呢? 我們看看官方文檔關(guān)于interface的說(shuō)法:
This is because when a class implements an interface, only the instance side of the class is checked. Since the constructor sits in the static side, it is not included in this check.
意思就是當(dāng)class實(shí)現(xiàn)一個(gè)接口的時(shí)候, 只會(huì)檢查實(shí)例面, 靜態(tài)面是不檢查的, 所以說(shuō)找不到.
那么, 哪些是靜態(tài)部分, 哪些是實(shí)例部分呢? 我們寫一段ts,
class C1 {
static s1: number = 5
public s2: number = 0
constructor() {
}
}
把代碼編譯成js
var C1 = (function () {
function C1() {
this.s2 = 0; //實(shí)例面
}
C1.s1 = 5; //靜態(tài)面
return C1;
}());
這里可以看出來(lái), 因?yàn)閠s里面的class, 其實(shí)編譯成js, 還是一個(gè)function, 而且是function里面的function, 那么外function就是靜態(tài)面, 內(nèi)function就是實(shí)例面, 內(nèi)function當(dāng)然沒(méi)有new.
注意, 只有當(dāng)class實(shí)現(xiàn)一個(gè)接口的時(shí)候, 才是檢查實(shí)例面, 當(dāng)類型以參數(shù)傳入時(shí), 是檢查靜態(tài)面的, 例如
interface IObjConstructor {
new <T>() : T;
add(a1:number, a2:number) : number
}
class C1 {
constructor() {
}
add(a1:number, a2:number) : number {
return a1 + a2
}
}
function create(c : IObjConstructor) : C1 {
return new c()
}
這段代碼會(huì)得到一個(gè)錯(cuò)誤
Property 'add' is missing in type 'typeof C1'.
那么, 我們要同時(shí)約束類的構(gòu)造函數(shù)和其它的屬性函數(shù), 要怎么做呢?
要解決這個(gè)問(wèn)題, 我們用create函數(shù)約束構(gòu)造函數(shù), 用接口約束其它屬性函數(shù), 例如:
interface IObjConstructor {
new <T>() : T;
}
interface IObjAction{
add(a1:number, a2:number) : number;
}
class C1 implements IObjAction {
constructor() {
}
add(a1:number, a2:number) : number {
return a1 + a2
}
}
function create<T extends IObjAction>(c : IObjConstructor) : T{
return new c<T>()
}
const c1 = create(C1)
console.log(c1.add(4, 5)) // = 9
這里IObjConstructor 約束構(gòu)造函數(shù), new用了泛型, 根據(jù)調(diào)用的類型T生成一個(gè)類型T的實(shí)例, C1實(shí)現(xiàn)IObjAction, 約束其它的函數(shù).
由于C1傳入到create, 并不會(huì)自動(dòng)識(shí)別為IObjAction , 所以create函數(shù)的泛型類型T繼承IObjAction, 讓new最終生成的類型屬于IObjAction, .
到這里已經(jīng)用typescript實(shí)現(xiàn)了工廠模式.