[React Framework] Chap 1 - Phác thảo cấu trúc

Phần gây bối rối nhất với newbie khi nhìn vào bộ framework này có lẽ là cách các class liên kết với nhau (AbstractFactory, AbstractResourceModel, ObjectManager, Singleton,… )
image

Chúng ta sẽ thử tìm hiểu từ Service, tại sao lại là Service ư ? Vì nó không chứa lifecycle của React, mà chỉ chứa các code logic input, ouput. Ví dụ với CategoryService là một service ít code logic nhất.

import CoreService from "../CoreService";
import ServiceFactory from "../../framework/factory/ServiceFactory";
import CategoryResourceModel from "../../resource-model/catalog/CategoryResourceModel";
import QueryService from "../QueryService";
import SyncConstant from "../../view/constant/SyncConstant";
import Config from "../../config/Config";

export class CategoryService extends CoreService {
    static className = 'CategoryService';
    resourceModel = CategoryResourceModel;

    async getListCategory(parentId) {
        ...
    }

}

let categoryService = ServiceFactory.get(CategoryService);

export default categoryService;

:red_circle: Kết luận 1: Các class tạo nên 1 service bao gồm

image

:black_square_button: Xem tiếp CoreService

import ResourceModelFactory from "../framework/factory/ResourceModelFactory";
import ObjectManager from "../framework/ObjectManager";

export default class CoreService {
    getResourceModel(resourceModel) {
        if(!resourceModel) {
            if (!this.compiledResourceModel) {
                this.compiledResourceModel = ResourceModelFactory.get(this.resourceModel);
            }
            return ObjectManager.get(this.compiledResourceModel);
        }
        return ObjectManager.get(ResourceModelFactory.get(resourceModel));
    }
    ...
}

:red_circle: Kết luận 2: CoreService được tạo nên từ ObjectManager và ResourceModelFactory

:black_square_button: Xem tiếp ObjectManager ta nhận thấy đây chỉ là 1 class thuần.

export class ObjectManager {
    instances = {};
    get(Class) {
        let className = Class.className;
        if (!className) {
            return new Class();
        }
        if(!this.instances[className]) {
            this.instances[className] = new Class();
        }
        return this.instances[className];
    }
}
let objectManager = new ObjectManager();
export default objectManager;

:black_square_button: Xem ResourceModelFactory

import AbstractFactory from "./AbstractFactory";

export class ResourceModelFactory extends AbstractFactory {
    get(object) {
        return this.getObject(`resource_model`, object);
    }

}
let resourceModelFactory = new ResourceModelFactory();
export default resourceModelFactory;

:black_square_button: Xem AbstractFactory

import Extension from "../Extension";

export default class AbstractFactory {
    create(entity) {
        return new entity();
    }
    getObject(type, object) {
        return Extension.get(type.toLowerCase(), object);
    }
}

:black_square_button: Xem tiếp Extension ta nhận thấy đây chỉ là 1 class thuần.

import config from '../extension/config'
export class Extension {
  ExtensionConfig = config();
  generatedClasses = {};
  ...
}

:red_circle: Kết luận 3: ResourceModelFactory kế thừa từ AbstractFactory, AbstractFactory được tạo nên từ Extension

:black_square_button: Xem tiếp ServiceFactory

import AbstractFactory from "./AbstractFactory";
import ObjectManager from "../ObjectManager";

export class ServiceFactory extends AbstractFactory {
    get(object) {
        return ObjectManager.get(this.getObject(`Service`, object));
    }
}
let serviceFactory = new ServiceFactory();
export default serviceFactory;

:red_circle: Kết luận 4: ServiceFactory kế thừa từ AbstractFactory và được tạo nên từ ObjectManager

:black_square_button: Xem tiếp CategoryResourceModel

import AbstractResourceModel from "../AbstractResourceModel";
import SyncConstant from "../../view/constant/SyncConstant";

export default class CategoryResourceModel extends AbstractResourceModel {
    static className = 'CategoryResourceModel';
    constructor(props) {
        super(props);
        this.state = {
            resourceName : 'Category',
            dataType: SyncConstant.TYPE_CATEGORY
        };
    }
}

:black_square_button: Xem AbstractResourceModel, tới đây thì đã là lifecycle của React

import {Component} from 'react';
import Singleton from "./Singleton"
import Config from '../config/Config';
import SyncContant from "../view/constant/SyncConstant";

export default class AbstractResourceModel extends Component {

    constructor(props) {
        super(props);
        this.state = {
            resourceName: '',
            dataType: ''
        }
    }

    getResource() {
        if (
            Config.dataTypeMode
            && this.state.dataType
            && Config.dataTypeMode[this.state.dataType] === SyncContant.OFFLINE_MODE
        ) {
            return Singleton.getOffline(this.state.resourceName);
        }
        return Singleton.getOnline(this.state.resourceName);
    }

    getResourceOnline() {
        return Singleton.getOnline(this.state.resourceName);
    }

    getResourceOffline() {
        return Singleton.getOffline(this.state.resourceName);
    }
    ...
}

:black_square_button: Xem Singleton

import { ... } from '../data/omc/index';
import Config from '../config/Config';
import {... } from '../data/indexeddb/index';
import OmcLocation from "../data/omc/OmcLocation";
import IndexedDbCart from "../data/indexeddb/IndexedDbCart";
import DataResourceFactory from "../framework/factory/DataResourceFactory";
import {fire} from "../event-bus";
import ObjectManager from "../framework/ObjectManager";

let resources = {
    'OmcUser' : OmcUser,
    ...
};

export class Singleton{
    constructor(props) {
        let eventDataBefore = {
            resources: resources
        };
        fire('constructor_singleton_before', eventDataBefore);
        resources = eventDataBefore.resources;
    }

    getOnline(name) {
        return this.get(Config.platform, name);
    }

    getOffline(name) {
        return this.get(Config.db, name);
    }

    get(prefix, name) {
        return ObjectManager.get(DataResourceFactory.get(resources[prefix + name]));
    }
}
let singleton = new Singleton();
export default singleton;

:black_square_button: Xem tiếp DataResourceFactory

import AbstractFactory from "./AbstractFactory";

export class DataResourceFactory extends AbstractFactory {
    get(object) {
        return this.getObject(`data_resource`, object);
    }
}

let dataResourceFactory = new DataResourceFactory();
export default dataResourceFactory;

:red_circle: Kết luận 5:

  • CategoryResourceModel kế thừa từ AbstractResourceModel
  • AbstractResourceModel sử dụng Singleton,
  • Singleton được tạo từ DataResourceFactoryObjectManager
  • DataResourceFactory kế thừa từ AbstractFactory

OK sơ bộ thì cấu trúc liên kết các class trông sẽ như thế này, có thể sẽ chưa đầy đủ vì ngoài Service sẽ còn nhiều thứ khác như Component, Container, Epic, …

Trong bài sau chúng ta sẽ cài đặt và cấu hình một project ReactJS , sau đó dựng bộ khung framework dựa trên cấu trúc này.

2 Likes

Chuẩn bị lập course về Magestore POS Framework thôi

1 Like