• Backend Weekly
  • Posts
  • Part 12: Interpreter and Memento Method Design Patterns (GoF)

Part 12: Interpreter and Memento Method Design Patterns (GoF)

We will explore the Interpreter and Memento method Design Patterns under the Behavioral Design Patterns.

In partnership with

Hello “👋

Welcome to another week, another opportunity to become a Great Backend Engineer.

Today’s issue is brought to you by MBProjects→ MBProjects is a project-based learning platform designed specifically for backend engineers. It’s your opportunity to work on 100+ real-world backend projects that mirror actual problems you’d encounter in the industry.

Before we get started, I have a few announcements:

I have a special gift for you: You will love this one.

Try the internet’s easiest File API

Tired of spending hours setting up file management systems? Pinata’s File API makes it effortless. With simple integration, you can add file uploads and retrieval to your app in minutes, allowing you to focus on building features instead of wasting time on unnecessary configurations. Our API provides fast, secure, and scalable file management without the hassle of maintaining infrastructure.

In this series, I will explore Design Patterns, their types, the GoF design patterns, drawbacks, and benefits for backend engineers.

This comes from my new Vue.js book on “Vue Design Patterns”. However, I’m only transferring the knowledge to backend engineers in this series.

Today, we will explore the Interpreter and Memento Design Patterns under the Behavioral Design Patterns.

Let’s get started quickly.

What is a Visitor Pattern?

The Interpreter Pattern is useful because it allows you to define the grammar of a language and interpret sentences in that language by implementing an interpreter. This pattern is particularly beneficial when you need to process structured, domain-specific languages or symbolic expressions.

By creating classes that represent each rule in the grammar, the Interpreter Pattern enables parsing, evaluating, and executing sentences within the language, making it ideal for tasks like mathematical expression evaluation, rule-based logic systems, and programming language compilers.

Let’s take a look at an example, in an access control system, you might have rules that define whether a user has access based on their roles or permissions. The Interpreter Pattern allows you to evaluate these rules dynamically and adjust access based on different conditions.

// Expression Interface
class PermissionExpression {
    interpret(context) {
        throw new Error("Method 'interpret()' must be implemented.");
    }
}

// Role Expression
class RoleExpression extends PermissionExpression {
    constructor(role) {
        super();
        this.role = role;
    }

    interpret(context) {
        return context.roles.includes(this.role);
    }
}

// And Expression for Permissions
class AndExpression extends PermissionExpression {
    constructor(left, right) {
        super();
        this.left = left;
        this.right = right;
    }

    interpret(context) {
        return this.left.interpret(context) && this.right.interpret(context);
    }
}

// Or Expression for Permissions
class OrExpression extends PermissionExpression {
    constructor(left, right) {
        super();
        this.left = left;
        this.right = right;
    }

    interpret(context) {
        return this.left.interpret(context) || this.right.interpret(context);
    }
}

// Client code
const context = { roles: ["Admin", "Editor"] };
const adminAccess = new RoleExpression("Admin");
const editorAccess = new RoleExpression("Editor");
const andAccess = new AndExpression(adminAccess, editorAccess);

console.log(andAccess.interpret(context));  // Output: true

The rule-based logic is encapsulated in individual classes (RoleExpression, AndExpression, OrExpression), making it easy to adjust and evaluate complex access rules. You can add more roles or permissions without modifying the existing rule structure, enhancing flexibility.

Why the Interpreter Pattern is Useful

The Interpreter Pattern is particularly beneficial for scenarios where you need to parse and evaluate expressions in a defined grammar. Its main advantages include:

  • Simplifies the implementation of DSLs: Provides a structured way to define and interpret domain-specific languages.

  • Makes complex grammar easy to represent and modify: Allows you to encapsulate each grammar rule in a separate class, promoting modularity.

  • Enables flexible parsing and evaluation: Facilitates dynamic parsing and evaluation, making it adaptable to user input or custom expressions.

  • Supports rule-based logic systems: Ideal for systems that rely on evaluating rule-based expressions.

  • Promotes reusability and extensibility: New expressions can be added without altering existing classes, making the language extensible.

By using the Interpreter Pattern, you can create systems that are more modular, maintainable, and adaptable, especially when working with structured expressions or DSLs.

What is a Memento Pattern?

The Memento Pattern is a behavioral design pattern that is particularly useful when you want to capture and restore the state of an object without exposing its internal details. This pattern is commonly used to implement undo and redo functionalities in applications, allowing you to roll back to a previous state when needed.

Why the Memento Pattern is Useful

  1. State Restoration: The Memento pattern allows saving an object’s state at a particular moment so that it can be restored later. This is very useful in applications such as text editors, games, or complex simulations where users may need to undo/redo changes.

  2. Encapsulation of State: It encapsulates the state of an object in a way that prevents external objects from accessing the internal details of the object whose state is being saved. This encapsulation maintains the principles of object-oriented design by preserving the integrity of the object being restored.

  3. Simplifies Complexity for Clients: Clients can store or restore states without being concerned about the internal workings of the objects. The object’s state can be rolled back without direct interference, which simplifies handling complex object structures and workflows.

  4. Non-Intrusive to Business Logic: The Memento pattern separates state-saving functionality from the primary business logic of the object. This keeps the logic clean and focused, while the caretaker class (which requests saving/restoring state) manages state transitions as needed.

Here an example, where the Memento pattern is used to save and restore states, providing an intuitive way to manage and revert object states as needed without directly exposing or modifying their internals.

// Memento Class
class Memento {
    constructor(state) {
        this.state = state;
    }
    getState() {
        return this.state;
    }
}

// Originator Class
class Originator {
    constructor() {
        this.state = '';
    }
    setState(state) {
        this.state = state;
    }
    saveStateToMemento() {
        return new Memento(this.state);
    }
    restoreStateFromMemento(memento) {
        this.state = memento.getState();
    }
}

// Caretaker Class
class Caretaker {
    constructor() {
        this.mementoList = [];
    }
    add(memento) {
        this.mementoList.push(memento);
    }
    get(index) {
        return this.mementoList[index];
    }
}

// Usage
const originator = new Originator();
const caretaker = new Caretaker();

originator.setState('State #1');
caretaker.add(originator.saveStateToMemento());

originator.setState('State #2');
caretaker.add(originator.saveStateToMemento());

originator.setState('State #3');
console.log('Current State:', originator.state);

// Restore to previous state
originator.restoreStateFromMemento(caretaker.get(0));
console.log('Restored State:', originator.state);

Other Examples and Use Cases:

  • Undo/Redo Functionality in Text Editors: In a text editor, whenever a user makes changes, the state can be stored as a memento. When the user clicks "Undo," the previous state can be restored.

  • State Restoration in Games: When a player reaches a checkpoint, the game's state is saved. If the player fails later, the game can revert to that checkpoint.

  • Transactional Systems: In applications where changes need to be committed or rolled back (e.g., banking, booking systems), the Memento pattern can be used to save a state before a transaction and revert it if the transaction fails.

That will be all for today. I like to keep this newsletter short.

Don’t miss it. Share with a friend

Did you learn any new things from this newsletter this week? Please reply to this email and let me know. Feedback like this encourages me to keep going.

See you on Next Week.

Remember to start learning backend engineering from our courses:

Top 5 Remote Backend Jobs this week

Here are the top 5 Backend Jobs you can apply to now.

👨‍💻 SAP Fioneer
✍️ Backend Engineer
đź“ŤRemote
đź’° Click on Apply for salary details
Click here to Apply for this role.

👨‍💻 AArete
✍️ Backend Engineer
đź“ŤRemote, Worldwide
đź’° Click on Apply for salary details
Click here to Apply for this role.

👨‍💻 FREE NOW
✍️ Backend Engineer (m/f/d) - Barcelona
đź“ŤRemote, Worldwide
đź’° Click on Apply for salary details
Click here to Apply for this role.

👨‍💻 FREE NOW
✍️ Backend Engineer (m/f/d) - Madrid
đź“ŤRemote
đź’° Click on Apply for salary details
Click here to Apply for this role.

Want more Remote Backend Jobs? Visit GetBackendJobs.com

Backend Engineering Resources

Whenever you're ready

There are 4 ways I can help you become a great backend engineer:

1. The MB Platform: Join 1000+ backend engineers learning backend engineering on the MB platform. Build real-world backend projects, track your learnings and set schedules, learn from expert-vetted courses and roadmaps, and solve backend engineering tasks, exercises, and challenges.

2. ​The MB Academy:​ The “MB Academy” is a 6-month intensive Advanced Backend Engineering BootCamp to produce great backend engineers.

3. MB Video-Based Courses: Join 1000+ backend engineers who learn from our meticulously crafted courses designed to empower you with the knowledge and skills you need to excel in backend development.

4. GetBackendJobs: Access 1000+ tailored backend engineering jobs, manage and track all your job applications, create a job streak, and never miss applying. Lastly, you can hire backend engineers anywhere in the world.

LAST WORD đź‘‹ 

How am I doing?

I love hearing from readers, and I'm always looking for feedback. How am I doing with The Backend Weekly? Is there anything you'd like to see more or less of? Which aspects of the newsletter do you enjoy the most?

Hit reply and say hello - I'd love to hear from you!

Stay awesome,
Solomon

I moved my newsletter from Substack to Beehiiv, and it's been an amazing journey. Start yours here.

Reply

or to participate.