Reputation: 33988
I am trying to port (in a reduced manner) the following sample to typescript, as I want to DEMO the abstract factory pattern in typescript.
https://gerardnico.com/wiki/lang/java/dao
So far the code I have created is the following (structure only)
export default class Customer{
public id: string;
public firstName: string;
public lastName: string;
}
import Customer from "./Customer";
export default interface ICustomerDAO{
insertCustomer(): number;
deleteCustomer(): boolean;
findCustomer(): Customer;
updateCustomer(): boolean;
listCustomers(): Customer[];
}
import CustomerDAO from "./ICustomerDAO";
import SharepointListDAOFactory from "./SharepointListDAOFactory";
import JsonDAOFactory from "./JsonDAOFactory";
export default abstract class DAOFactory{
public static SHAREPOINTLIST: number = 1;
public static REMOTEJSON : number = 2;
public abstract getCustomerDAO(): CustomerDAO;
public getDAOFactory(whichFactory: number): DAOFactory {
switch (whichFactory) {
case 1:
return new SharepointListDAOFactory();
case 2:
return new JsonDAOFactory();
default :
return null;
}
}
}
import DAOFactory from "./DAOFactory";
import ICustomerDAO from "./ICustomerDAO";
import JsonCustomerDAO from "./JsonCustomerDAO";
export default class JsonDAOFactory extends DAOFactory{
getCustomerDAO(): ICustomerDAO{
return new JsonCustomerDAO();
}
}
import DAOFactory from "./DAOFactory";
import ICustomerDAO from "./ICustomerDAO";
import SharepointCustomerDao from "./SharepointCustomerDAO";
export default class SharepointListDAOFactory extends DAOFactory{
getCustomerDAO(): ICustomerDAO{
return new SharepointCustomerDao();
}
}
import ICustomerDAO from "./ICustomerDAO";
import Customer from "./Customer";
//actual implementation
export default 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;
}
}
import ICustomerDAO from "./ICustomerDAO";
import Customer from "./Customer";
//actual implementations
export default 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;
}
}
Code compiles, but I am having issues in how to use the abstract class, from the client or caller of the above code, which is an SPFx REACT component
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';
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(1);
break;
case "JSON":
break;
}
return null;
}
public setInitialState(): void {
this.state = {
items: []
};
}
}
I am not sure about the syntax or how to translate these lines to typescript
DAOFactory OracleDbFactory =
DAOFactory.getDAOFactory(DAOFactory.DAOORACLEDB);
// Create a DAO
CustomerDAO custDAO =
OracleDbFactory.getCustomerDAO();
Upvotes: 1
Views: 1712
Reputation: 191729
Currently your code would require instantiation of a DAOFactory
to have acess to the getDAOFactory
method:
const daoFactory = new DAOFactory;
However you can't do this since DAOFactory
is abstract.
Instead the factory function doesn't need to be an object method -- it can be a class method (static) or even just a function.
const getDAOFactory = (whichFactory: number): DAOFactory => {
switch (whichFactory) {
case 1:
return new SharepointListDAOFactory();
case 2:
return new JsonDAOFactory();
default :
return null;
}
}
Now you can just call OracleDbFactory = getDAOFactory(DAOFactory.DAOORACLEDB);
(type is implicit from the return type of the function).
I do wonder why you need this extra layer of abstraction though. Seems like something like custDao = getDao(DaoTypes.Customer)
would suffice.
Upvotes: 1