mercredi 8 avril 2020

Good implementation for Factory Pattern with Generics and overriding - Typescript

the code in below works for its purpose, my question is to discuss about some bad practice in this implementation of factory with generics types, and in general have some nice suggestion by people with more skills :)

I have several classes that extend a base class called "RTLink". All these classes have some logic in common in their construction, for these reason I decided to make a factory pattern with generics called RTLinkFactory. Many classes that extends RTLink don't need further logic but several other need more logic that is not expressed in RTLinkFactory, so I thought to extends RTLinkFactory to reuse basic logic and make some other custom logic.

export abstract class RTLinkFactory <L extends RTLink> {
    constructor( protected linkConstructor: { new(...args: any[]): L }) {
    }
    public async make <R1 extends RTResource, R2 extends RTResource> (resource: R1, linkedResource: R2, schema: any): Promise<L> {
        const link: L = new this.linkConstructor(schema);
        // Common logic
        link.key = resource.key;
        link.linkedTo = linkedResource.key;
        link.createdAt = new Date();
        link.updatedAt = link.createdAt;

        return link;
    }
}

export abstract class RTLink {
    public key!: RTResourceKey;
    public linkedTo!: RTResourceKey;
    public type: string = 'UNSPECIFIED';
    public createdAt!: Date;
    public updatedAt!: Date;
}


export class ActionLinkFactory extends RTLinkFactory<Action> {
    public async make <R1 extends RTResource, R2 extends RTResource> (user: R1, initiative: R2, schema: any): Promise<Action> {
        // Custom logic here
        // ... for example: changes on schema
        return super.make(user, initiative, schema);
    }
}

export class Action extends RTLink {
    public type = 'ACTION';
    public product: string;
    public webLink: string;

    public constructor(schema: ActionSchema) {
        super();
        this.product = schema.product;
        this.webLink = schema.webLink;
    }
}

Aucun commentaire:

Enregistrer un commentaire