DEV Community

Cover image for Most common design patterns for Front-End with JavaScript (Real-world examples)
Luis Castillo
Luis Castillo

Posted on

50 8

Most common design patterns for Front-End with JavaScript (Real-world examples)

Hello everyone, in this post, I want to show you how can easily we can implement some common design patterns in your projects. These patterns help us to have a maintainable, flexible, and readable code. You will see the advantages when you need to add more functionalities without do a lot of modifications in the code.

So now, let's code!! ๐Ÿ’ป

1.- Module pattern.

The module pattern is one of the most common patterns in the JavaScript world and it's it is very useful to encapsulate the logic of functions and variables in the same scope and manage the access of them, something similar to access modifiers (public, private, etc).

There are a lot of examples on the internet with different variations but I tried to create an example as simple it is possible.
Note: We can see this pattern in ES6 with import/export syntax.
Complexity: โšก

var module = (function () {
  let options = {color:"red"}
  /*
    private code here
  */
  const setSize = function () {
    options["size"] = 12;
  };

  /*
    public code here
  */
  return {
    getOptions: function () {
      setSize();
      return options;
    }
  };
})();
module.getOptions();
Enter fullscreen mode Exit fullscreen mode

2.- Strategy pattern.

The Strategy design pattern is very used when we have similar tasks and we need to change between tasks in the runtime.
This pattern helps us to eliminate a lot of if-else sentences, to do that simply we have to encapsulate the tasks in small chunks and use an object literal to access our concrete strategy.

Component Strategy

This pattern is very simple to implement in javascript because you don't need interfaces or any hard implementation.
Use case: Imagine that we have a dropdown with different user types (normal user, admin, and guest), and we want to display a form on the same page dependence on which user type was selected.

Here is an example with React, but you can apply in other JS frameworks.

Complexity: โšกโšก

// React components section
import React from "react";
import UserForm  from "./userForm";
import AdminForm from "./adminForm";
import GuestForm from "./guestForm";

/*
* This object literal will help to encapsulate all the forms that could we have.
*/
const FormsManage = {
  user : {
    render(props){
      return <UserForm {...props} />
    }
  },
  admin:{
    render(props){
      return <AdminForm {...props} />
    }
  },
  guest:{
    render(props) {
      return <GuestForm {...props}/> 
    }
  }
};

/*
* Main form component
*/
const Form = (props) => {
  // here we are getting the form by type
  const userForm = FormsManage[props.type];
  return userForm.render(props);
};
export default Form;
Enter fullscreen mode Exit fullscreen mode

3.- Builder pattern.

The builder pattern is used when we need to create complex objects with different variations and also we want to have the flexibility to modify the construction process without impact the object representation in self.
I tried to create an example that we can use in the real-world.

Use case: How many times we need to transform the API data into a format that our third-party component understands, for this case, we can use the builder pattern to create the object that the component needs, and also separate the construction logic.

Complexity: โšกโšกโšก


/*
* Mock class
*/
class DataTable{
  constructor(data ,options){
    this.data = data;
    this.options = options
  }
  getData(){
    return this.data;
  }
}

/*
* Builder class to create DataTable objects.
*/
function DataTableBuilder () {
  let defualtOptions ={ width:100, height:200, headerFixed: false };

  /*
  * Method to make the format required.
  */
  function generateFormattedData(data,header){
    return data.map(item => {
      let result = {};
      item.forEach((val,idx) => {
          result[header[idx] || "df"+idx] = val;
      });
      return result;
    });
  };

  /*
  * Public steps methods
  */
  return {
    addHeader(header){
      this.header = header || [];
      return this;
    },
    addData(data){
      this.data = data || [];
      return this;
    },
    addOptions(options){
      this.options = { ...defualtOptions, ...options};
      return this;
    },
    build(){
      const formattedData = generateFormattedData(this.data,this.header);
      return new DataTable(formattedData,this.options);
    }
  }
};

/*
* Data needed to build the Datatable object 
*/
const header=["name","age","position"];
const rows = [["Luis",19,"Dev"],["Bob",23,"HR"], ["Michel",25,"Accounter"]];
const options = { headerFixed:true };

/*
*  Start to the builder process
*/
const dt = new DataTableBuilder()
                  .addHeader(header)
                  .addData(rows)
                  .addOptions(options)
                  .build();
dt.getData();
Enter fullscreen mode Exit fullscreen mode

Conclusion.

In the software development world exists many design patterns and all of them have their qualities, but it is work of us as Developers, understand and analyze which of them add real value to our project and not more problems or complexity.

If you have some design patterns that have been useful for you, please share in the discussion section or if you want to implement one of the previous ones and you need a hand, let me know and I can help you. ๐Ÿ˜‰

SurveyJS custom survey software

Build Your Own Forms without Manual Coding

SurveyJS UI libraries let you build a JSON-based form management system that integrates with any backend, giving you full control over your data with no user limits. Includes support for custom question types, skip logic, an integrated CSS editor, PDF export, real-time analytics, and more.

Learn more

Top comments (2)

Collapse
 
hashcode01 profile image
Hash โ€ข

How does this look ?

// React components section
import React from "react";
import UserForm  from "./userForm";
import AdminForm from "./adminForm";
import GuestForm from "./guestForm";

/*
* This object literal will help to encapsulate all the forms that could we have.
*/
const FormsManage = {
  user : UserForm,
  admin: AdminForm,
  guest:GuestForm
};

/*
* Main form component
*/
const Form = (props) => {
  // here we are getting the form by type
  const UserForm = FormsManage[props.type];
  return <UserForm  {...props} />
};
export default Form;

Enter fullscreen mode Exit fullscreen mode
Collapse
 
lukocastillo profile image
Luis Castillo โ€ข

Awesome bro, looks great!

nextjs tutorial video

Youtube Tutorial Series ๐Ÿ“บ

So you built a Next.js app, but you need a clear view of the entire operation flow to be able to identify performance bottlenecks before you launch. But how do you get started? Get the essentials on tracing for Next.js from @nikolovlazar in this video series ๐Ÿ‘€

Watch the Youtube series

๐Ÿ‘‹ Kindness is contagious

Please leave a โค๏ธ or a friendly comment on this post if you found it helpful!

Okay