在Typescript中扩展构建器

时间:2017-05-26 14:30:00

标签: angular typescript

是否可以使用此答案中提供的等效内容,但在Typescript中?

Subclassing a Java Builder class

以下是我到目前为止基类的内容:

export class ProfileBuilder {
    name: string;

    withName(value: string): ProfileBuilder {
        this.name= value;
        return this;
    }

    build(): Profile{
        return new Profile(this);
    }
}

export class Profile {
    private name: string;

    constructor(builder: ProfileBuilder) {
        this.name = builder.Name;
    }
}

扩展课程:

export class CustomerBuilder extends ProfileBuilder  {
    email: string;

    withEmail(value: string): ProfileBuilder {
        this.email = value;
        return this;
    }

    build(): Customer {
        return new Customer(this);
    }
}

export class Customer extends Profile {
    private email: string;

    constructor(builder: CustomerBuilder) {
        super(builder);
        this.email= builder.email;
    }
}

与其他线程一样,由于上下文的变化,我无法按此顺序构建客户:

let customer: Customer = new CustomerBuilder().withName('John')
                                              .withEmail('john@email.com')
                                              .build();

我目前正在尝试使用泛型来解决这个问题,但是在为我的setter方法返回this指针时遇到了麻烦(类型不能分配给类型T)。有什么想法吗?

2 个答案:

答案 0 :(得分:2)

我最近遇到了同样的要求,这是我的解决方案,如果我们创建一个配置文件构建器类,我们可以从我们的客户构建器扩展它,并使用super调用基础构建器。

class ProfileBuilder {
    private name: string;

    constructor() {
        this.name = undefined;
    }

    public withName(name: string) {
        this.name = name;
        return this;
    }

    public build() {
        return {
            name: this.name
        }
    }
}

class CustomerBuilder extends ProfileBuilder {
    private email: string;

    constructor() {
        super();

        this.email = undefined;
    }

    public withEmail(email: string) {
        this.email = email;
        return this;
    }

    public build() {
        const base = super.build();
        return {
            ...base,
            email: this.email
        }
    }
}

现在,您可以根据自己的要求创建客户:

const customer = new CustomerBuilder()
    .withName("John")
    .withEmail("john@email.com") 
    .build();

答案 1 :(得分:0)

找到解决方案!在我提到的另一个线程上查看不同的答案后,我最终创建了一个基本抽象类和构建器,然后为每个类/构建器对进行扩展:

abstract class BaseProfileBuilder<T extends BaseProfile, B extends BaseProfileBuilder<T, B>> {
    protected object: T;
    protected thisPointer: B;

    protected abstract createObject(): T;

    protected abstract getThisPointer(): B;

    constructor() {
        this.object = this.createObject();
        this.thisPointer = this.getThisPointer();
    }

    withName(value: string): B {
        this.object.name = value;
        return this.thisPointer;
    }

    build(): T {
        return this.object;
    }
}

abstract class BaseProfile {
    name: string;
}

class ProfileBuilder extends BaseProfileBuilder<Profile, ProfileBuilder> {
    createObject(): Profile {
        return new Profile();
    }

    getThisPointer(): ProfileBuilder {
        return this;
    }
}

class Profile extends BaseProfile {
}

class CustomerBuilder extends BaseProfileBuilder<Customer, CustomerBuilder>  {
    createObject(): Customer {
        return new Customer();
    }

    getThisPointer(): CustomerBuilder {
        return this;
    }

    withEmail(value: string): CustomerBuilder {
        this.object.email = value;
        return this;
    }
}

class Customer extends BaseProfile {
    email: string;
}


let customer: Customer = new CustomerBuilder().withName('John')
                                              .withEmail('john@email.com')
                                              .build();

console.log(customer);