Skip to main content

design-patterns-implementation

Apply appropriate design patterns (Singleton, Factory, Observer, Strategy, etc.) to solve architectural problems. Use when refactoring code architecture, implementing extensible systems, or following SOLID principles.

소스 정보

저장소
tmcfarlane/oh-my-cursor
최근 소스 활동
2026년 2월 26일 23:41
감지된 SKILL.md 언어
영어
스타
110
포크
13

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
design-patterns-implementation
description
Apply appropriate design patterns (Singleton, Factory, Observer, Strategy, etc.) to solve architectural problems. Use when refactoring code architecture, implementing extensible systems, or following SOLID principles.
# Design Patterns Implementation ## Overview Apply proven design patterns to create maintainable, extensible, and testable code architectures. ## When to Use - Solving common architectural problems - Making code more maintainable and testable - Implementing extensible plugin systems - Decoupling components - Following SOLID principles - Code reviews identifying architectural issues ## Common Design Patterns ### 1. **Singleton Pattern** Ensure a class has only one instance with global access. ```typescript class DatabaseConnection { private static instance: DatabaseConnection; private connection: any; private constructor() { this.connection = this.createConnection(); } public static getInstance(): DatabaseConnection { if (!DatabaseConnection.instance) { DatabaseConnection.instance = new DatabaseConnection(); } return DatabaseConnection.instance; } private createConnection() { return { /* connection logic */ }; } } // Usage const db1 = DatabaseConnection.getInstance(); const db2 = DatabaseConnection.getInstance(); // db1 === db2 (same instance) ``` ### 2. **Factory Pattern** Create objects without specifying exact classes. ```python from abc import ABC, abstractmethod class PaymentProcessor(ABC): @abstractmethod def process_payment(self, amount: float) -> bool: pass class StripeProcessor(PaymentProcessor): def process_payment(self, amount: float) -> bool: # Stripe-specific logic return True class PayPalProcessor(PaymentProcessor): def process_payment(self, amount: float) -> bool: # PayPal-specific logic return True class PaymentProcessorFactory: @staticmethod def create_processor(processor_type: str) -> PaymentProcessor: if processor_type == 'stripe': return StripeProcessor() elif processor_type == 'paypal': return PayPalProcessor() else: raise ValueError(f'Unknown processor: {processor_type}') # Usage processor = PaymentProcessorFactory.create_processor('stripe') processor.process_payment(100.00) ``` ### 3. **Observer Pattern** Define one-to-many dependency for event notification. ```javascript class Subject { constructor() { this.observers = []; } attach(observer) { this.observers.push(observer); } detach(observer) { this.observers = this.observers.filter(obs => obs !== observer); } notify(data) { this.observers.forEach(observer => observer.update(data)); } } class Observer { update(data) { console.log('Received update:', data); } } // Usage const subject = new Subject(); const observer1 = new Observer(); const observer2 = new Observer(); subject.attach(observer1); subject.attach(observer2); subject.notify({ event: 'data_changed' }); ``` ### 4. **Strategy Pattern** Define family of algorithms and make them interchangeable. ```java interface CompressionStrategy { byte[] compress(byte[] data); } class ZipCompression implements CompressionStrategy { public byte[] compress(byte[] data) { // ZIP compression logic return data; } } class GzipCompression implements CompressionStrategy { public byte[] compress(byte[] data) { // GZIP compression logic return data; } } class FileCompressor { private CompressionStrategy strategy; public FileCompressor(CompressionStrategy strategy) { this.strategy = strategy; } public void setStrategy(CompressionStrategy strategy) { this.strategy = strategy; } public byte[] compressFile(byte[] data) { return strategy.compress(data); } } // Usage FileCompressor compressor = new FileCompressor(new ZipCompression()); compressor.compressFile(fileData); // Change strategy at runtime compressor.setStrategy(new GzipCompression()); compressor.compressFile(fileData); ``` ### 5. **Decorator Pattern** Add responsibilities to objects dynamically. ```typescript interface Coffee { cost(): number; description(): string; } class SimpleCoffee implements Coffee { cost(): number { return 5; } description(): string { return 'Simple coffee'; } } class MilkDecorator implements Coffee { constructor(private coffee: Coffee) {} cost(): number { return this.coffee.cost() + 2; } description(): string { return this.coffee.description() + ', milk'; } } class SugarDecorator implements Coffee { constructor(private coffee: Coffee) {} cost(): number { return this.coffee.cost() + 1; } description(): string { return this.coffee.description() + ', sugar'; } } // Usage let coffee: Coffee = new SimpleCoffee(); console.log(coffee.cost()); // 5 coffee = new MilkDecorator(coffee); console.log(coffee.cost()); // 7 coffee = new SugarDecorator(coffee); console.log(coffee.cost()); // 8 console.log(coffee.description()); // "Simple coffee, milk, sugar" ``` ### 6. **Repository Pattern** Abstract data access logic. ```python from abc import ABC, abstractmethod from typing import List, Optional class UserRepository(ABC): @abstractmethod def find_by_id(self, user_id: int) -> Optional[User]: pass @abstractmethod def find_all(self) -> List[User]: pass @abstractmethod def save(self, user: User) -> User: pass @abstractmethod def delete(self, user_id: int) -> bool: pass class DatabaseUserRepository(UserRepository): def __init__(self, db_connection): self.db = db_connection def find_by_id(self, user_id: int) -> Optional[User]: result = self.db.query('SELECT * FROM users WHERE id = ?', user_id) return User.from_dict(result) if result else None def find_all(self) -> List[User]: results = self.db.query('SELECT * FROM users') return [User.from_dict(r) for r in results] def save(self, user: User) -> User: self.db.execute('INSERT INTO users (...) VALUES (...)', user.to_dict()) return user def delete(self, user_id: int) -> bool: return self.db.execute('DELETE FROM users WHERE id = ?', user_id) ``` ### 7. **Dependency Injection** Invert control by injecting dependencies. ```typescript // Bad: Hard-coded dependencies class OrderService { private db = new MySQLDatabase(); // Tightly coupled private email = new GmailService(); // Tightly coupled createOrder(order: Order) { this.db.save(order); this.email.send(order.customer_email, 'Order created'); } } // Good: Dependency injection interface Database { save(entity: any): void; } interface EmailService { send(to: string, subject: string): void; } class OrderService { constructor( private db: Database, private email: EmailService ) {} createOrder(order: Order) { this.db.save(order); this.email.send(order.customer_email, 'Order created'); } } // Usage - easy to test with mocks const service = new OrderService( new MySQLDatabase(), new GmailService() ); // Test with mocks const testService = new OrderService( new MockDatabase(), new MockEmailService() ); ``` ## Best Practices ### ✅ DO - Choose patterns that solve actual problems - Keep patterns simple and understandable - Document why patterns were chosen - Consider testability - Follow SOLID principles - Use dependency injection - Prefer composition over inheritance ### ❌ DON'T - Apply patterns without understanding them - Over-engineer simple solutions - Force patterns where they don't fit - Create unnecessary abstraction layers - Ignore team familiarity with patterns ## When to Use Each Pattern | Pattern | Use Case | |---------|----------| | **Singleton** | Database connections, configuration managers | | **Factory** | Creating objects based on runtime conditions | | **Observer** | Event systems, pub/sub, reactive programming | | **Strategy** | Algorithms that can be swapped at runtime | | **Decorator** | Adding features dynamically without inheritance | | **Repository** | Abstracting data access from business logic | | **Adapter** | Making incompatible interfaces work together | | **Facade** | Simplifying complex subsystems | | **Command** | Undo/redo, task queuing, macro recording | ## Resources - "Design Patterns" by Gang of Four - "Head First Design Patterns" by Freeman & Freeman - refactoring.guru/design-patterns
GitHub에서 보기