Skip to content

Instantly share code, notes, and snippets.

@g33kChris
Last active April 29, 2018 19:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save g33kChris/4e942083742fb1ddd964844f40fae89c to your computer and use it in GitHub Desktop.
Save g33kChris/4e942083742fb1ddd964844f40fae89c to your computer and use it in GitHub Desktop.
Typescript Builder Pattern (Generic to Specific Implementation)
import { injectable } from 'inversify';
import BuilderBase from './BuilderBase';
import IBlogPostViewModelBuilder from './IBlogPostViewModelBuilder';
import IBlogPostViewModel from '@g33kchris/g33kchris.dto.ui/IBlogPostViewModel';
import IContentHeroViewModel from '@g33kchris/g33kchris.dto.ui/IContentHeroViewModel';
import IContentBodyViewModel from '@g33kchris/g33kchris.dto.ui/IContentBodyViewModel';
import IContentMetaViewModel from '@g33kchris/g33kchris.dto.ui/IContentMetaViewModel';
import IRelatedContentViewModel from '@g33kchris/g33kchris.dto.ui/IRelatedContentViewModel';
import IPostsCollectionViewModel from '@g33kchris/g33kchris.dto.ui/IPostsCollectionViewModel';
import BlogPostViewModel from '@g33kchris/g33kchris.dto.ui/BlogPostViewModel';
// Concrete implementation of the Builder
@injectable()
export class BlogPostViewModelBuilder implements IBlogPostViewModelBuilder {
private _builder: BuilderBase<IBlogPostViewModel>; // <= Leverages the generic BuilderBase to build up an object.
constructor() {
this._builder = new BuilderBase<IBlogPostViewModel>(BlogPostViewModel);
}
withAvailable(available: boolean): IBlogPostViewModelBuilder {
this._builder
.with(vm => Object.assign({}, vm, { available })); // <= Build expressions!
return this;
}
withHero(hero: IContentHeroViewModel): IBlogPostViewModelBuilder {
this._builder
.with(vm => Object.assign({}, vm, { hero }));
return this;
}
withBody(body: IContentBodyViewModel): IBlogPostViewModelBuilder {
this._builder
.with(vm => Object.assign({}, vm, { body }));
return this;
}
withMeta(meta: IContentMetaViewModel): IBlogPostViewModelBuilder {
this._builder
.with(vm => Object.assign({}, vm, { meta }));
return this;
}
withRelated(related: IRelatedContentViewModel): IBlogPostViewModelBuilder {
this._builder
.with(vm => Object.assign({}, vm, { related }));
return this;
}
withOtherPosts(otherPosts: IPostsCollectionViewModel): IBlogPostViewModelBuilder {
this._builder
.with(vm => Object.assign({}, vm, { otherPosts }))
return this;
}
build(): IBlogPostViewModel {
return this._builder.build();
}
}
import IBuilderBase from './IBuilderBase';
export default class BuilderBase<T> implements IBuilderBase<T> {
private _actions: Array<(result: T) => T> = []; // <= This holds an array of build expressions to run on build
private _result: T;
constructor(type: { new(): T }){
// This will new us up an instance of an object without having to know the type!
// https://stackoverflow.com/questions/17382143/how-to-create-a-new-object-from-type-parameter-in-generic-class-in-typescript
this._result = new type();
}
with(action: (result: T) => T): IBuilderBase<T> {
this._actions.push(action);
return this;
}
build(): T {
for (let a of this._actions) {
this._result = a(this._result);
}
return this._result;
}
}
import IContentHeroViewModel from '@g33kchris/g33kchris.dto.ui/IContentHeroViewModel';
import IContentBodyViewModel from '@g33kchris/g33kchris.dto.ui/IContentBodyViewModel';
import IContentMetaViewModel from '@g33kchris/g33kchris.dto.ui/IContentMetaViewModel';
import IRelatedContentViewModel from '@g33kchris/g33kchris.dto.ui/IRelatedContentViewModel';
import IPostsCollectionViewModel from '@g33kchris/g33kchris.dto.ui/IPostsCollectionViewModel';
import IBlogPostViewModel from '@g33kchris/g33kchris.dto.ui/IBlogPostViewModel';
// Introductory Builder Pattern implementation (very specific build members)
export default interface IBlogPostViewModelBuilder {
withAvailable(available: boolean): IBlogPostViewModelBuilder;
withHero(hero: IContentHeroViewModel): IBlogPostViewModelBuilder;
withBody(body: IContentBodyViewModel): IBlogPostViewModelBuilder;
withMeta(meta: IContentMetaViewModel): IBlogPostViewModelBuilder;
withRelated(related: IRelatedContentViewModel): IBlogPostViewModelBuilder;
withOtherPosts(withOtherPosts: IPostsCollectionViewModel): IBlogPostViewModelBuilder;
build(): IBlogPostViewModel;
}
// An interface to build an implementation of the BuilderBase
export default interface IBuilderBase<T> {
with(action: (result: T) => T): IBuilderBase<T> ;
build(): T;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment