0
\$\begingroup\$

I wanted to implement abstract factory method in typescript with react for sharepoint framework webpart.

So I tried to translate ideas from this Java tutorial. I don't have method implementations yet, but so far it compiles, and I want to know if I am doing it right:

component .tsx file

import * as React from 'react';
import styles from './TypescriptDesignPatterns02AbstractFactory.module.scss';
import { ITypescriptDesignPatterns02AbstractFactoryProps } from './ITypescriptDesignPatterns02AbstractFactoryProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { ITypescriptDesignPatterns02AbstractFactoryState } from './ITypescriptDesignPatterns02AbstractFactoryState';
import SharepointListDAOFactory from './Factory/SharepointListDAOFactory';
import DAOFactory from './Factory/DAOFactory';
import ICustomerDAO from './Factory/ICustomerDAO';
import DataSources from './Factory/DatasourcesEnum';
import Customer from './Factory/Customer';

export default class TypescriptDesignPatterns02AbstractFactory extends React.Component<ITypescriptDesignPatterns02AbstractFactoryProps, ITypescriptDesignPatterns02AbstractFactoryState> {
  constructor(props: ITypescriptDesignPatterns02AbstractFactoryProps, state: ITypescriptDesignPatterns02AbstractFactoryState) {
    super(props);
    this.setInitialState();
  }

  public render(): React.ReactElement<ITypescriptDesignPatterns02AbstractFactoryProps> {
    switch(this.props.datasource) {
      case "Sharepoint":
        let sharepointlistdaofactory: SharepointListDAOFactory =   DAOFactory.getDAOFactory(DataSources.SharepointList);
        let customerSharepointDAO: ICustomerDAO = sharepointlistdaofactory.getCustomerDAO();
        this.state = {
          items: customerSharepointDAO.listCustomers()
        };
        break;
      case "JSON":
        let jsondaofactory: SharepointListDAOFactory =   DAOFactory.getDAOFactory(DataSources.JsonData);
        let customerJsonDAO: ICustomerDAO = jsondaofactory.getCustomerDAO();
        this.state = {
          items: customerJsonDAO.listCustomers()
        };
        break;
    }
    return null;
  }

  public setInitialState(): void {
    this.state = {
      items: []
    };
  }



}

DAOFactory.ts

import ICustomerDAO from "./ICustomerDAO";
import SharepointListDAOFactory from "./SharepointListDAOFactory";
import JsonDAOFactory from "./JsonDAOFactory";
import DataSources from "./DatasourcesEnum";


abstract class DAOFactory {

    public static SHAREPOINTLIST: number = 1;
    public static REMOTEJSON : number = 2;

    public abstract getCustomerDAO(): ICustomerDAO;

    public  static getDAOFactory(whichFactory: DataSources): DAOFactory {
        switch (whichFactory) {
          case DataSources.SharepointList:
            return new SharepointListDAOFactory();
          case DataSources.JsonData:
            return new JsonDAOFactory();
          default  :
            return null;
        }
      }
}

export default DAOFactory;

ICustomerDAO.ts

import Customer from "./Customer";

 interface ICustomerDAO{
    insertCustomer(): number;
    deleteCustomer(): boolean;
    findCustomer(): Customer;
    updateCustomer(): boolean;
    listCustomers(): Customer[];
}

export default ICustomerDAO;

Jsoncustomerdao.ts

import ICustomerDAO from "./ICustomerDAO";
import Customer from "./Customer";

export  class JsonCustomerDAO implements ICustomerDAO{
    public insertCustomer(): number{
        return 1;
    }

    public deleteCustomer(): boolean{
        return true;
    }

    public findCustomer(): Customer{
        return new Customer();
    }

    public updateCustomer(): boolean{
        return true;
    }

    public listCustomers(): Customer[]{
        let c1= new Customer();
        let c2= new Customer();
        let list: Array<Customer> = [c1, c2 ];
        return list;
    }
}

Sharepoint customer dao

import ICustomerDAO from "./ICustomerDAO";
import Customer from "./Customer";

 class SharepointCustomerDao implements ICustomerDAO{
    public insertCustomer(): number{
        return 1;
    }

    public deleteCustomer(): boolean{
        return true;
    }

    public findCustomer(): Customer{
        return new Customer();
    }

    public updateCustomer(): boolean{
        return true;
    }

    public listCustomers(): Customer[]{
        let c1= new Customer();
        let c2= new Customer();
        let list: Array<Customer> = [c1, c2 ];
        return list;
    }
}

export default SharepointCustomerDao;

SharepointListDaoFactory.ts

import DAOFactory from "./DAOFactory";
import ICustomerDAO from "./ICustomerDAO";
import SharepointCustomerDao from "./SharepointCustomerDAO";

class SharepointListDAOFactory extends DAOFactory{
    getCustomerDAO(): ICustomerDAO{
        return new SharepointCustomerDao();
    }
}

export default SharepointListDAOFactory;

Json DAO Factory

import DAOFactory from "./DAOFactory";
import ICustomerDAO from "./ICustomerDAO";
import JsonCustomerDAO from "./JsonCustomerDAO";


class JsonDAOFactory extends DAOFactory{
    getCustomerDAO(): ICustomerDAO{
        return new JsonCustomerDAO();
    }
}

export default JsonDAOFactory;
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

render() should know nothing about the source of the data. It only has to know about the ICustomerDAO.listCustomers().

If props are known in the constructor, the DAO objects must be set there too.

I'm not into Typescript that much, but it'd be something like (I've put commented code to show you how this would evolve when you needed more DAaccess):

import * as React from 'react';
import styles from './TypescriptDesignPatterns02AbstractFactory.module.scss';
import { ITypescriptDesignPatterns02AbstractFactoryProps } from './ITypescriptDesignPatterns02AbstractFactoryProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { ITypescriptDesignPatterns02AbstractFactoryState } from './ITypescriptDesignPatterns02AbstractFactoryState';
import SharepointListDAOFactory from './Factory/SharepointListDAOFactory';
import DAOFactory from './Factory/DAOFactory';
import ICustomerDAO from './Factory/ICustomerDAO';
import DataSources from './Factory/DatasourcesEnum';
import Customer from './Factory/Customer';

export default class TypescriptDesignPatterns02AbstractFactory extends React.Component<ITypescriptDesignPatterns02AbstractFactoryProps, ITypescriptDesignPatterns02AbstractFactoryState> {

    private customerDao: ICustomerDAO;
    // private userDao: IUserDAO;

    constructor(props: ITypescriptDesignPatterns02AbstractFactoryProps, state: ITypescriptDesignPatterns02AbstractFactoryState) {
        super(props);
        this.setInitialState();
        this.setDaos(props.datasource); // TODO: Inject DAO with Inversify JS or similar tools
    }

    public render(): React.ReactElement<ITypescriptDesignPatterns02AbstractFactoryProps> {
        this.state = {
            items: this.customerDao.listCustomers(),
            // users: this.userDao.listUsers()
        };

        return null;
    }

    // TODO: If you are not using this method anywhere else, set it to private
    public setInitialState(): void {
        this.state = {
            items: []
        };
    }

    private setDaos(datasource): void {

        const data: any = datasource == "Sharepoint" ? DataSources.SharepointList : JsonData; // Now, you only have 2 datasources, so you don't need that switch statement

        this.customerDao = DAOFactory.getDAOFactory(data).getCustomerDAO();
        // this.userDao = DaoFactory.getDaoFactory(DataSources.SharepointList).getUserDAO();
    }
}
\$\endgroup\$
2
  • \$\begingroup\$ can you post the corrections? \$\endgroup\$ Dec 29, 2017 at 10:43
  • \$\begingroup\$ @LuisValencia I edited the answer with some code. \$\endgroup\$ Dec 31, 2017 at 12:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.