VibeKoding / Ensiklopedia ยท Fondasi KuatEnsiklopedia ยท Fondasi Kuat / Fundamentals of Design PatternsFundamentals of Design Patterns
VK

Fundamentals of Design PatternsFundamentals of Design Patterns

๐Ÿ“š Ensiklopedia ยท Fondasi KuatEnsiklopedia ยท Fondasi Kuat ๐ŸŒ Dual Bahasa (ID / EN) โšก VibeKoding Native

Ensiklopedia VibeKoding: Fundamentals of Design Patterns.Ensiklopedia VibeKoding: Fundamentals of Design Patterns.

๐Ÿ’ก Tips Praktis๐Ÿ’ก Pro Tip

Why is your code always "works but messy"? You may have encountered this: when requirements change, the code needs major rewrites; you want to reuse a piece of logic but find it tangled with other code. Design patterns are "code organization recipes" summarized by predecessors to help you write flexible, maintainable code. This chapter helps you understand the most practical design patterns โ€” not memorizing them by rote, but understanding "which pattern for which scenario."Why is your code always "works but messy"? You may have encountered this: when requirements change, the code needs major rewrites; you want to reuse a piece of logic but find it tangled with other code. Design patterns are "code organization recipes" summarized by predecessors to help you write flexible, maintainable code. This chapter helps you understand the most practical design patterns โ€” not memorizing them by rote, but understanding "which pattern for which scenario."

What will you learn in this article?What will you learn in this article?

ChapterContentCore Concepts
Chapter 1What are design patternsThe essence and classification of patterns
Chapter 2Creational patternsHow to elegantly create objects
Chapter 3Structural patternsHow to organize code structure
Chapter 4Behavioral patternsHow to manage interactions between objects

After reading this chapter, you will master the most commonly used design patterns and be able to identify applicable scenarios and apply them flexibly in real projects.After reading this chapter, you will master the most commonly used design patterns and be able to identify applicable scenarios and apply them flexibly in real projects.

------

0. The Big Picture: The Essence of Design Patterns0. The Big Picture: The Essence of Design Patterns

Imagine you're learning to cook. You can figure everything out from scratch each time, or you can learn classic recipes โ€” recipes don't limit your creativity; they let you stand on the shoulders of those who came before. Design patterns are the "classic recipes" of the programming world.Imagine you're learning to cook. You can figure everything out from scratch each time, or you can learn classic recipes โ€” recipes don't limit your creativity; they let you stand on the shoulders of those who came before. Design patterns are the "classic recipes" of the programming world.

๐Ÿ’ก Tips Praktis๐Ÿ’ก Pro Tip

- Common Language: Say "use the Observer pattern here" and the team immediately understands your design intent - Experience Reuse: No need to step into the same traps others already fell into - Flexible Extension: Good patterns allow code to adapt to changes with minor modifications rather than major rewrites- Common Language: Say "use the Observer pattern here" and the team immediately understands your design intent - Experience Reuse: No need to step into the same traps others already fell into - Flexible Extension: Good patterns allow code to adapt to changes with minor modifications rather than major rewrites

Use the interactive component below to browse the classification and uses of common design patterns:Use the interactive component below to browse the classification and uses of common design patterns:

------

1. Creational Patterns: How to Elegantly Create Objects1. Creational Patterns: How to Elegantly Create Objects

1.1 Singleton Pattern1.1 Singleton Pattern

Scenario: Only one instance is needed globally, such as a configuration manager, logger, or database connection pool.Scenario: Only one instance is needed globally, such as a configuration manager, logger, or database connection pool.

javascript
class ConfigManager { static instance = null static getInstance() { if (!ConfigManager.instance) { ConfigManager.instance = new ConfigManager() } return ConfigManager.instance } constructor() { this.config = {} } } // No matter how many times you call it, it's always the same instance const a = ConfigManager.getInstance() const b = ConfigManager.getInstance() console.log(a === b) // true

1.2 Factory Pattern1.2 Factory Pattern

Scenario: Creating different types of objects based on different conditions, where the caller doesn't need to know the specific creation details.Scenario: Creating different types of objects based on different conditions, where the caller doesn't need to know the specific creation details.

javascript
function createNotification(type, message) { switch (type) { case 'email': return { send: () => console.log(`Send email: ${message}`) } case 'sms': return { send: () => console.log(`Send SMS: ${message}`) } case 'push': return { send: () => console.log(`Push notification: ${message}`) } default: throw new Error(`Unknown notification type: ${type}`) } } // The caller doesn't care about the specific implementation const notification = createNotification('email', 'Hello') notification.send()

------

2. Structural Patterns: How to Organize Code Structure2. Structural Patterns: How to Organize Code Structure

2.1 Adapter Pattern2.1 Adapter Pattern

Scenario: Two interfaces are incompatible and need a "converter plug." For example, the data format returned by an old API doesn't match what a new component expects.Scenario: Two interfaces are incompatible and need a "converter plug." For example, the data format returned by an old API doesn't match what a new component expects.

javascript
// Format returned by the old API const oldApi = { getUserInfo: () => ({ user_name: 'Zhang San', user_age: 25 }) } // Adapter: convert to new format function adaptUser(oldUser) { return { name: oldUser.user_name, age: oldUser.user_age } } const user = adaptUser(oldApi.getUserInfo()) // { name: 'Zhang San', age: 25 }

2.2 Decorator Pattern2.2 Decorator Pattern

Scenario: Adding new functionality to an object without modifying the original code. Like putting a case on your phone โ€” the phone's functionality stays the same, but you gain protection.Scenario: Adding new functionality to an object without modifying the original code. Like putting a case on your phone โ€” the phone's functionality stays the same, but you gain protection.

javascript
// Basic log function function log(message) { console.log(message) } // Decorator: add timestamp function withTimestamp(fn) { return (message) => fn(`[${new Date().toISOString()}] ${message}`) } // Decorator: add log level function withLevel(fn, level) { return (message) => fn(`[${level}] ${message}`) } const enhancedLog = withTimestamp(withLevel(log, 'INFO')) enhancedLog('Service started successfully') // [2025-01-15T10:30:00.000Z] [INFO] Service started successfully

------

3. Behavioral Patterns: How to Manage Interactions Between Objects3. Behavioral Patterns: How to Manage Interactions Between Objects

3.1 Observer Pattern3.1 Observer Pattern

Scenario: When one object's state changes, other objects need to be automatically notified. For example, after a user places an order, you need to simultaneously send an email, deduct inventory, and log the event.Scenario: When one object's state changes, other objects need to be automatically notified. For example, after a user places an order, you need to simultaneously send an email, deduct inventory, and log the event.

javascript
class EventEmitter { constructor() { this.listeners = {} } on(event, callback) { if (!this.listeners[event]) this.listeners[event] = [] this.listeners[event].push(callback) } emit(event, data) { (this.listeners[event] || []).forEach(cb => cb(data)) } } const bus = new EventEmitter() bus.on('order:created', (order) => console.log('Send confirmation email', order.id)) bus.on('order:created', (order) => console.log('Deduct inventory', order.id)) bus.emit('order:created', { id: 'ORD-001' })

3.2 Strategy Pattern3.2 Strategy Pattern

Scenario: The same operation has multiple algorithms/strategies that need to be switched at runtime. For example, different sorting methods or different pricing rules.Scenario: The same operation has multiple algorithms/strategies that need to be switched at runtime. For example, different sorting methods or different pricing rules.

javascript
const pricingStrategies = { normal: (price) => price, vip: (price) => price * 0.8, svip: (price) => price * 0.6 } function calculatePrice(price, memberLevel) { const strategy = pricingStrategies[memberLevel] || pricingStrategies.normal return strategy(price) } calculatePrice(100, 'vip') // 80 calculatePrice(100, 'svip') // 60

Use the interactive component below to try out the effects of different design patterns:Use the interactive component below to try out the effects of different design patterns:

------

4. Approach to choosing a Design Pattern4. Approach to choosing a Design Pattern

Problem You EncounterRecommended PatternCore Idea
Only one global instance neededSingletonControl instance count
Create different objects based on conditionsFactoryEncapsulate creation logic
Incompatible interfaces need conversionAdapterWrap with a conversion layer
Dynamically add functionalityDecoratorLayer-by-layer enhancement
State changes need to notify multiple partiesObserverPublish-subscribe decoupling
Multiple algorithms need runtime switchingStrategyEncapsulate algorithms as objects
๐Ÿ’ก Tips Praktis๐Ÿ’ก Pro Tip

Design patterns are not "the more the better." Over-engineering is just as bad as no design. Only use patterns where flexibility is genuinely needed; solve simple problems with simple solutions. Remember the KISS principle: Keep It Simple, Stupid.Design patterns are not "the more the better." Over-engineering is just as bad as no design. Only use patterns where flexibility is genuinely needed; solve simple problems with simple solutions. Remember the KISS principle: Keep It Simple, Stupid.

------

5. AI-Powered: Using LLMs to Learn and Apply Design Patterns5. AI-Powered: Using LLMs to Learn and Apply Design Patterns

LLMs can help you identify scenarios suitable for design patterns in your code and provide specific refactoring solutions.LLMs can help you identify scenarios suitable for design patterns in your code and provide specific refactoring solutions.

5.1 Identifying Applicable Patterns5.1 Identifying Applicable Patterns

> Prompt:> Prompt:

> ```> ```

> Analyze the following code and determine if there are opportunities> Analyze the following code and determine if there are opportunities

> to improve it with design patterns.> to improve it with design patterns.

> If so, please explain:> If so, please explain:

> 1. Problems with the current code> 1. Problems with the current code

> 2. Which design pattern is recommended> 2. Which design pattern is recommended

> 3. Refactored code example> 3. Refactored code example

> 4. Why this pattern fits this scenario> 4. Why this pattern fits this scenario

>>

> [Paste your code]> [Paste your code]

> ```> ```

5.2 Learning Patterns with Concrete Scenarios5.2 Learning Patterns with Concrete Scenarios

> Prompt:> Prompt:

> ```> ```

> Using a "food delivery ordering system" as a real scenario,> Using a "food delivery ordering system" as a real scenario,

> demonstrate the application of these design patterns:> demonstrate the application of these design patterns:

> - Factory Pattern: creating different types of orders> - Factory Pattern: creating different types of orders

> - Observer Pattern: order status change notifications> - Observer Pattern: order status change notifications

> - Strategy Pattern: different delivery fee calculation rules> - Strategy Pattern: different delivery fee calculation rules

>>

> Use JavaScript code examples. For each pattern, first show the> Use JavaScript code examples. For each pattern, first show the

> problem without the pattern, then show the improvement with it.> problem without the pattern, then show the improvement with it.

> ```> ```

5.3 Judging Over-Engineering5.3 Judging Over-Engineering

> Prompt:> Prompt:

> ```> ```

> Review the following code and determine if there is over-engineering.> Review the following code and determine if there is over-engineering.

> Are there unnecessary abstractions, unused design patterns,> Are there unnecessary abstractions, unused design patterns,

> or premature optimizations?> or premature optimizations?

> If so, suggest how to simplify, following the KISS principle.> If so, suggest how to simplify, following the KISS principle.

>>

> [Paste your code]> [Paste your code]

> ```> ```

๐Ÿ’ก Tips Praktis๐Ÿ’ก Pro Tip

Having AI explain design patterns using business scenarios you're familiar with is much more effective than reading abstract UML diagrams. But remember: AI may tend to recommend more complex solutions โ€” you need to judge for yourself whether they're truly necessary.Having AI explain design patterns using business scenarios you're familiar with is much more effective than reading abstract UML diagrams. But remember: AI may tend to recommend more complex solutions โ€” you need to judge for yourself whether they're truly necessary.

------

6. Summary6. Summary

  1. Creational Patterns: Solve "how to create objects" problems, making the creation process more flexibleCreational Patterns: Solve "how to create objects" problems, making the creation process more flexible
  2. Structural Patterns: Solve "how to organize code" problems, making the structure clearerStructural Patterns: Solve "how to organize code" problems, making the structure clearer
  3. Behavioral Patterns: Solve "how objects interact" problems, enabling looser couplingBehavioral Patterns: Solve "how objects interact" problems, enabling looser coupling
  4. Flexible Application: Choose based on actual scenarios โ€” don't use patterns just for the sake of using themFlexible Application: Choose based on actual scenarios โ€” don't use patterns just for the sake of using them
  5. ๐Ÿ’ก Tips Praktis๐Ÿ’ก Pro Tip

    The essence of design patterns is managing change. Good design makes the changing parts easy to modify while keeping the stable parts unchanged. When writing code, ask yourself: "If requirements change, how many places would I need to modify?" โ€” if the answer is "many places," you might need a design pattern to help.The essence of design patterns is managing change. Good design makes the changing parts easy to modify while keeping the stable parts unchanged. When writing code, ask yourself: "If requirements change, how many places would I need to modify?" โ€” if the answer is "many places," you might need a design pattern to help.

    ------

    Further ReadingFurther Reading

    • Classic Book: GoF's Design Patterns: Elements of Reusable Object-Oriented Software is the foundational work on design patterns.Classic Book: GoF's Design Patterns: Elements of Reusable Object-Oriented Software is the foundational work on design patterns.
    • Modern Perspective: Many patterns become more concise in JavaScript thanks to language features (closures, higher-order functions).Modern Perspective: Many patterns become more concise in JavaScript thanks to language features (closures, higher-order functions).
    • Practical Advice: Understand the problem first, then consider patterns. Don't hold a hammer looking for nails.Practical Advice: Understand the problem first, then consider patterns. Don't hold a hammer looking for nails.
    • Advanced Learning: Learn the SOLID principles โ€” they are the guiding philosophy behind design patterns.Advanced Learning: Learn the SOLID principles โ€” they are the guiding philosophy behind design patterns.