What are some strategies for circumventing the need for two switches?

My LayerEditor class consists of two private methods:

export class LayerEditor {
       public layerManager: LayerManager;

       constructor() {
           this.layerManager = new LayerManager(this);     
       }
  
       private executeCommand() {
        switch (this.layerManager.editableLayer.type) {
            case LayerType.common:
                this.commandManager.set(new SelectExistCommand(this.reonMap));
                break;

            case LayerType.point:
                this.commandManager.set(new SelectExistPointCommand(this.reonMap));
                break;
        }
    }

    private createTools(): EditorTools {
        switch (this.layerManager.editableLayer.type) {
            case LayerType.common:
                return new CommonTools(new CommonToolsFactory());

            case LayerType.point:
                return new PointTools(new PointToolsFactory());
        }
    }
}

Is there a way to combine the two switches into one method for better flexibility in OOP?

The LayerManager class is responsible for managing layers:

class LayerManager {
    public selectedLayer: TreeNode;
    public editableLayer: Layer;
    public polygonsArea: string;
    private readonly layers: TreeNode[];

    constructor(private layerEditor: LayerEditor) {
        this.layers = this.layerEditor.r.layersManager.editableLayers;
    }

    getLayers() {
        return this.layers;
    }

    selectLayer(layerId: string) {
        this.selectedLayer = { ...this.layerEditor.r.layersManager.getLayerConfig(layerId), enabled: true };
        this.layerEditor.r.state.changeTreeNode(this.selectedLayer);
    }

    createLayerObject() {
        this.editableLayer = FactoryLayer.create(this.selectedLayer.id, this.selectedLayer.type, this.layerEditor.r);
    }
}

The CommandManager class handles commands, working as a dispatcher and storing all commands.

class CommandManager {
        public currentCommand: Command;
        protected commands: Command[] = [];
        protected undoCommand: Command;
    
        constructor(public layerEditor: LayerEditor) {}
    
        set(command: Command): void {
            if (command === this.currentCommand) return;
            this.currentCommand = command;
            this.commands.push(this.currentCommand);
        }
    
        execute(): void {
            this.currentCommand.execute();
        }
    
        undo(): void {
            this.currentCommand.undo();
        }
    
        redo(): void {
            this.currentCommand.redo();
        }
    
        cancel(): void {
            while (this.commands.length) {
                this.currentCommand = this.commands.pop();
                this.undo();
            }
        }
    
        complete(): void {
            this.currentCommand.complete();
        }
    }

If you require any further information, do let me know.

Answer №1

To simplify your code and make it more organized, consolidate all split decisions into a single entity. Instead of having multiple classes like PointTools, PointToolsFactory, SelectExistPointCommand, etc., consider using a unified class called PointConfig. Ensure that both configurations align with the same interface, allowing for interchangeable use of tools returned by this.config.createTools().

Follow the Factory Method Pattern which is easily understandable in languages like C# similar to TypeScript. While you may have attempted this with a class FactoryLayer, refine it so that the factory serves as the sole decision-maker.

You can structure your code as outlined below:

// Define interface for LayerConfig
interface LayerConfig {
  id: string;
  type: SemanticLayerType;
  fields: Record<string, FieldConfig>;
  createTools(): Button[];
  createSelectCommand(map: ReonMap): Command;
}

// Implement PointConfig class
class PointConfig implements LayerConfig {
  // Implementation details here
}

// Implement PolygonConfig class
class PolygonConfig implements LayerConfig {
  // Implementation details here
}

// Create Layer class
class Layer {
  // Constructor and other methods
}

// Create FactoryLayer class
export class FactoryLayer {
  static create(layerId: string, layerType: LayerType): Layer {
    // Factory method implementation
  }
}

// Create LayerEditor class
export class LayerEditor {
  // Constructor and methods
}

Answer №2

I have recently attempted to consolidate common elements and explore the functionalities of Typescript.

Both the private methods involve the use of

this.layerManager.editableLayer.type
. Now, I have introduced an optional parameter and made changes to return multiple data types. Below is the revised code snippet. If required, you can set a default parameter as type = 'execute' and provide the parameter as create when necessary:

private checkTool( type?: string): EditorTools | void {

    const layerManagerType = this.layerManager.editableLayer.type

    switch(layerManagerType) {
        case LayerType.common:
                return (type === 'execute') ? 
                  this.commandManager.set(new SelectExistCommand(this.reonMap)) 
                  : new CommonTools(new CommonToolsFactory());
                break;
        case LayerType.point:
            return ( type === 'execute') ? 
              this.commandManager.set(new SelectExistPointCommand(this.reonMap)) 
              : new PointTools(new PointToolsFactory());
    }

}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The websocket server implemented in Node.js with the use of the "ws" library is exhibiting a peculiar behavior where it disconnects clients at random intervals,

My WebSocket server implementation is quite simple: const WebSocket = require('ws'); const wss = new WebSocket.Server( { server: server, path: "/ws" }); wss.on('connection', function connection(ws, req) { console.log("Connect ...

"Is there a way to dynamically remap an array only when there are changes

One of the challenges I am facing is with a component called Page, which contains two components - Editor and Preview. Page has an array called items. [ { value: 0, text: 'Item 1' }, ... ] This array items is passed ...

"Enhance your website with a unique Bootstrap 5 carousel featuring multiple

As a beginner in Bootstrap, I am currently working on an ecommerce template to learn about Bootstrap 5. I am interested in creating a carousel that displays multiple slides at once, like a products slider with left and right arrows. Is this possible in Bo ...

Guide on setting up redux store from server component using next.js and app router

I'm currently working with Next.js 13, React, and Redux to handle state management. My main objective is to fetch initial data on the server side and present it on the client side. Although I assumed this would be a typical approach with Redux and Ne ...

Unable to manipulate the marker with the leaflet library

Currently, I am utilizing react.js with the leaflet library and would like to enable marker movement on the map when clicked, instead of adding a new one. Below is the code snippet I am working with: import React from "react"; import { MapConta ...

Blurry text issue observed on certain mobile devices with Next.js components

There continues to be an issue on my NextJS page where some text appears blurry on certain mobile devices, particularly iPhones. This problem is only present on two specific components - both of which are interactive cards that can be flipped to reveal the ...

What is an alternative approach to passing arguments to an event handler in a React render component without using a lambda function?

In my React app, I've learned that using lambda functions in the property of a render component can harm application performance. For example: <ConfirmSmsModal modal={args.modal} smsCheck={async (code: string) => { return await this._vm ...

Why am I receiving the error message 'Uncaught TypeError: results is not a function' while utilizing the map function?

Struggling to grasp the concept of the map function and puzzled by why my output is showing [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined], even though I've provided the correct this value as per the documenta ...

Encountering a 400 bad request error while trying to post data using

const fetch = require("node-fetch").default; let iApi = express.Router(); iApi.post("/update/:name/:value", async (req, res) => { const name = req.params["name"]; ...

Optimal method for detecting changes in a React webpage

As I create React hook components that utilize Material-UI input controls, I have searched extensively but have not found a satisfactory example. My goal is to display a popup message to the user if they have made changes to an input field, checkbox, rad ...

Obtain varied results from the Knockout module

In my application, I am utilizing Knockout and Typescript. One of the classes in my code is as follows: class Address { State :string; ZIP: string; Street: string; } I want to create a component that will handle the updating of an object of ...

How can I dynamically update a div without refreshing the page by using an onclick event on a

When working on my project, I found helpful insights from this Stack Overflow thread. The structure of template-comparison.php involves fetching code from header.php to ensure the page displays properly. However, the actual "fetch code" process remains un ...

Determining changes in an object with Angular 2 and Ionic 2

Q) How can I detect changes in an object with multiple properties bound to form fields without adding blur events to each individual field? I want to avoid cluttering the page with too many event listeners, especially since it's already heavy. For e ...

How can we reset multiple selected values (mui chips) in a React Material-UI Autocomplete field when changing the value in a different field?

Is there a way to clear the mui-chips in Material UI Autocomplete TextField when the value in another field is changed? I have been struggling with clearing the subtype value when the Type value changes. Although I can update the drop-down options based on ...

What is the process for obtaining the Tag from a React Component?

Not the HTML DOM element tag, the JSX tag, the react class name. As I work on creating an editor, adding items to the canvas array requires me to check and call the appropriate method based on what is being added. A simplified version of my idea: changeS ...

Leveraging Angular 6: Implementing custom scripts on a component basis and verifying their presence

I need some help with a script that I want to run on a specific component only. I've managed to add the script to the component, but there are a few issues that I'm unsure how to fix. When I go to the component, the script is added to the DOM b ...

custom dialog box appears using ajax after successful action

Recently, I created a custom dialog/modal box with the following code: <div id="customdialog" class="modal"> <div class="modal__overlay"></div> <div class="modal__content"> <h2><strong>Hello</strong&g ...

Eliminate a specific choice from a drop-down menu in an Angular application

I am implementing a feature where clicking on a button adds more select drop downs. I want to ensure that the selected options in these new dropdowns do not duplicate any already chosen options. Below is the code snippet used for the select drop down: < ...

What's the best way to keep track of the number of objects I've created

Using this HTML code, I can create member objects. However, I also need to determine the count of these member objects for certain calculations. Additionally, when a member object is deleted, the count of member objects should be reduced accordingly. The ...

Bring in Bootstrap and the Carousel plugin using Webpack Encore

Currently, I am tackling an issue within my Symfony project that involves Webpack Encore and the loading of Bootstrap and the Carousel plugin. The problem may stem from how I import Bootstrap, as it seems to partially work when I import the file like this ...