Advanced Patterns
As JavaScript applications grow, developers rely on proven design patterns to keep code readable, maintainable, and scalable.
Patterns are not rules. They are reusable solutions to common problems.
Why Patterns Matter
- Reduce repeated logic
- Improve code structure
- Make teams work consistently
- Help scale large applications
Most modern frameworks internally use these patterns.
Module Pattern
The module pattern helps encapsulate logic and expose only what is necessary.
const counterModule = (function () {
let count = 0;
function increment() {
count++;
return count;
}
return {
increment
};
})();
counterModule.increment();
This pattern uses closures to keep data private.
Factory Pattern
The factory pattern creates objects without exposing the creation logic.
function createUser(name, role) {
return {
name,
role,
describe() {
return `${name} is a ${role}`;
}
};
}
const user = createUser("Alex", "Developer");
Factories are flexible and easy to extend.
Singleton Pattern
The singleton pattern ensures only one instance of an object exists.
const settings = (function () {
let instance;
function createInstance() {
return { theme: "dark" };
}
return {
getInstance() {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
This is useful for configuration or shared state.
Observer Pattern
The observer pattern allows objects to react to changes in another object.
It is commonly used in:
- Event systems
- State management
- User interface updates
Example Concept
One object emits updates, and others listen and respond.
This pattern powers many UI libraries.
Composition Over Inheritance
Modern JavaScript favors composition instead of deep inheritance chains.
Instead of extending classes, small reusable functions are combined.
const canWalk = state => ({
walk: () => console.log(`${state.name} walks`)
});
const canTalk = state => ({
talk: () => console.log(`${state.name} talks`)
});
const person = name => {
let state = { name };
return Object.assign({}, canWalk(state), canTalk(state));
};
const user = person("Alex");
This approach is flexible and scalable.
When to Use Patterns
- When code becomes repetitive
- When structure starts breaking
- When scaling becomes difficult
Patterns should solve problems, not create unnecessary complexity.
Common Mistakes
- Overusing patterns
- Applying patterns too early
- Copying patterns without understanding
Patterns should feel natural, not forced.
Thumb Rules
- Patterns are tools, not goals
- Use simple solutions first
- Prefer readability over cleverness
- Choose patterns that fit the problem
What Comes Next?
You have now covered advanced JavaScript concepts used in real-world applications.
In the next lesson, we will build an object-oriented mini project.