Design and Pattern

Design patterns are reusable solutions to common software design problems, helping developers build cleaner, scalable, and maintainable systems. They act as templates for solving recurring issues in object creation, structure, and behavior.


What Are Design Patterns?

Design patterns are best practices in software engineering that emerged from decades of trial and error by experienced developers. They provide standardized approaches to recurring problems, ensuring that solutions are both efficient and easy to understand.

  • Origin: The concept was popularized in 1994 by the Gang of Four (Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides) in their book Design Patterns: Elements of Reusable Object-Oriented Software.
  • Purpose: They improve code readability, reusability, and maintainability, while reducing development time by avoiding reinventing solutions.

Types of Design Patterns

Design patterns are generally categorized into three main groups:

  • Creational Patterns – Focus on object creation mechanisms, making systems more flexible and reusable.
    Examples: Singleton, Factory Method, Abstract Factory, Builder, Prototype.
  • Structural Patterns – Deal with object composition, ensuring that parts of a system fit together efficiently.
    Examples: Adapter, Composite, Proxy, Decorator, Facade, Bridge.
  • Behavioral Patterns – Address communication between objects, defining how they interact and distribute responsibilities.
    Examples: Observer, Strategy, Command, State, Mediator, Iterator.

Why They Matter

  • Consistency: Provide proven solutions across projects.
  • Scalability: Make systems easier to expand and maintain.
  • Collaboration: Help teams communicate using a shared vocabulary.
  • Efficiency: Reduce bugs and speed up development by reusing established solutions.

Learn More

Here are some excellent resources to dive deeper into design patterns:


Luau Object Oriented Programming

A table in Lua is an object in more than one sense. Like objects, tables have a state. Like objects, tables have an identity (a selfness) that is independent of their values; specifically, two objects (tables) with the same value are different objects, whereas an object can have different values at different times, but it is always the same object. Like objects, tables have a life cycle that is independent of who created them or where they were created.

Check this video: https://youtu.be/g1iKA3lSFms?si=hHTzdD-2AMAPjl_j

Objects have their own operations. Tables also can have operations:

    Account = {balance = 0}
    function Account.withdraw (v)
      Account.balance = Account.balance - v
    end

This definition creates a new function and stores it in field withdraw of the Account object. Then, we can call it as

    Account.withdraw(100.00)

This kind of function is almost what we call a method. However, the use of the global name Account inside the function is a bad programming practice. First, this function will work only for this particular object. Second, even for this particular object the function will work only as long as the object is stored in that particular global variable; if we change the name of this object, withdraw does not work any more:

    a = Account; Account = nil
    a.withdraw(100.00)   -- ERROR!

Such behavior violates the previous principle that objects have independent life cycles.