Factory Method Pattern

Factory Method is a creational design pattern that provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created.

In this the users dont have to worry about the instantiation logic, they just need to call the factory method and get the object they need. It hides the complexity of object creation and provides a simple interface for users.

Benefits:

Drawbacks:

Without Factory Method

const type = "admin"; // or "moderator", "user"
const data = { id : 1, name: "Arun CS" };
let user: User;
switch (type) {
    case "admin":
        user = new Admin(data);
        user.setOptions({ canEdit: true, canDelete: true });
        user.setPermissions(["read", "write", "delete"]);
        break;
    case "moderator":
        user = new Moderator(data);
        user.setOptions({ canEdit: true });
        user.setPermissions(["read", "write"]);
        break;
    case "user":
        user = new User(data);
        user.setOptions({ canEdit: false });
        user.setPermissions(["read"]);
        break;
    default:
        throw new Error("Unknown user type");
}

Usage:

Without Factory Method In GO

type User interface {
    SetOptions(options map[string]interface{})
    SetPermissions(permissions []string)
}
type Admin struct {
    User
}
func (a *Admin) SetOptions(options map[string]interface{}) {
    // Set admin specific options
}
func (a *Admin) SetPermissions(permissions []string) {
    // Set admin specific permissions
}
// Similar for Moderator and User types 

With Factory Method

class UserFactory {
    static createUser(type: string, data: any): User {
        switch (type) {
            case "admin":
                return new Admin(data);
            case "moderator":
                return new Moderator(data);
            case "user":
                return new User(data);
            default:
                throw new Error("Unknown user type");
        }
    }
}

Usage:

const user = UserFactory.createUser("admin", { id: 1, name: "
Arun CS" });
user.setOptions({ canEdit: true, canDelete: true });
user.setPermissions(["read", "write", "delete"]);

With Factory Method In GO

type UserFactory interface {
    CreateUser(userType string, data map[string]interface{}) User
}

type UserFactoryImpl struct{}

func (f *UserFactoryImpl) CreateUser(userType string, data map[string]interface{}) User {
    switch userType {
    case "admin":
        return &Admin{Data: data}
    case "moderator":
        return &Moderator{Data: data}
    case "user":
        return &User{Data: data}
    default:
        panic("Unknown user type")
    }
}

Usage:

factory := &UserFactoryImpl{}
user := factory.CreateUser("admin", map[string]interface{}{
    "id": 1, 
    "name": "Arun CS",
})
user.SetOptions(map[string]interface{}{
    "canEdit": true, 
    "canDelete": true,
})
user.SetPermissions([]string{"read", "write", "delete"})
---
config:
  theme: redux
---
flowchart LR
    A["type == ?"] --> B["new Admin"]
    A --> C["new Moderator"] 
    A --> D["new User"]
    B --> E["setOptions"] 
    B --> F["setPermissions"]
    C --> G["setOptions"] 
    C --> H["setPermissions"]
    D --> I["setOptions"] 
    D --> J["setPermissions"]
    
    A@{ shape: diam}
    B@{ shape: rounded}
    C@{ shape: rounded}
    D@{ shape: rounded}
    style A fill:#2962FF