程序中经常会用到很多不同的设计模式, 而工厂模式的使用率, 是设计模式中使用率比较高的.
当我们用工厂模式的时候, 需要写一个Factory来创建各个类
interface IObjConstructor {
new <T>() : T;
}
function create(c : IObjConstructor) : C1 {
return new c()
}
代码里的create就是我们要的factory了, 然后我们写一个class实现IObjConstructor接口.
class C1 implements IObjConstructor {
constructor() {
}
}
这段代码看上去很正常, C1类实现了接口IObjConstructor, 但是编译会报错
Type 'C1' provides no match for the signature 'new <T>(): T'
奇怪了, 为什么说C1没有这个new属性呢? 我们看看官方文档关于interface的说法:
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.
意思就是当class实现一个接口的时候, 只会检查实例面, 静态面是不检查的, 所以说找不到.
那么, 哪些是静态部分, 哪些是实例部分呢? 我们写一段ts,
class C1 {
static s1: number = 5
public s2: number = 0
constructor() {
}
}
把代码编译成js
var C1 = (function () {
function C1() {
this.s2 = 0; //实例面
}
C1.s1 = 5; //静态面
return C1;
}());
这里可以看出来, 因为ts里面的class, 其实编译成js, 还是一个function, 而且是function里面的function, 那么外function就是静态面, 内function就是实例面, 内function当然没有new.
注意, 只有当class实现一个接口的时候, 才是检查实例面, 当类型以参数传入时, 是检查静态面的, 例如
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()
}
这段代码会得到一个错误
Property 'add' is missing in type 'typeof C1'.
那么, 我们要同时约束类的构造函数和其它的属性函数, 要怎么做呢?
要解决这个问题, 我们用create函数约束构造函数, 用接口约束其它属性函数, 例如:
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 约束构造函数, new用了泛型, 根据调用的类型T生成一个类型T的实例, C1实现IObjAction, 约束其它的函数.
由于C1传入到create, 并不会自动识别为IObjAction , 所以create函数的泛型类型T继承IObjAction, 让new最终生成的类型属于IObjAction, .
到这里已经用typescript实现了工厂模式.
网友评论