
Design Patterns Implementation
- 546 installs
- 305 repo stars
- Updated March 4, 2026
- aj-geddes/useful-ai-prompts
design-patterns-implementation is a coding skill that applies proven design patterns such as Singleton, Factory, Observer, and Strategy to refactor architecture and build extensible, testable systems following SOLID prin
About
design-patterns-implementation is a skill in aj-geddes/useful-ai-prompts that guides developers through selecting and applying proven design patterns to solve common architectural problems. The skill covers Singleton, Factory, Observer, Strategy, and additional patterns with reference guides, quick-start steps, and best practices for creating maintainable, extensible, and testable code. Developers reach for design-patterns-implementation when refactoring tangled service layers, introducing extension points, or aligning new modules with SOLID principles. The skill pairs pattern selection guidance with concrete implementation workflows rather than abstract theory alone.
- Applies Singleton, Factory, Observer, Strategy and other classic patterns
- Enforces SOLID principles during implementation and refactoring
- Creates maintainable, extensible and testable code architectures
- Decouples components for plugin systems and modular design
- Triggered on code reviews that flag architectural issues
Design Patterns Implementation by the numbers
- 546 all-time installs (skills.sh)
- Ranked #231 of 1,352 Code Review & Quality skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/aj-geddes/useful-ai-prompts --skill design-patterns-implementationAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 546 |
|---|---|
| repo stars | ★ 305 |
| Last updated | March 4, 2026 |
| Repository | aj-geddes/useful-ai-prompts ↗ |
Which design pattern fits this refactoring problem?
Apply proven design patterns like Singleton, Factory, Observer and Strategy when refactoring architecture or building extensible systems.
Who is it for?
Developers refactoring architecture or building extensible backend systems who need guided pattern selection and SOLID-aligned implementation.
Skip if: Quick bug fixes, greenfield prototypes with no structural debt, or teams seeking framework-specific cookbook recipes only.
When should I use this skill?
Refactoring code architecture, implementing extensible systems, or applying SOLID principles with concrete design patterns.
What you get
Refactored modules using appropriate design patterns with improved extensibility, maintainability, and testability.
- refactored pattern-based modules
- architecture decision guidance
By the numbers
- Documents Singleton, Factory, Observer, Strategy, and additional design patterns
Files
Design Patterns Implementation
Table of Contents
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
Quick Start
Minimal working example:
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();
// ... (see reference guides for full implementation)Reference Guides
Detailed implementations in the references/ directory:
| Guide | Contents |
|---|---|
| Singleton Pattern | Singleton Pattern |
| Factory Pattern | Factory Pattern |
| Observer Pattern | Observer Pattern |
| Strategy Pattern | Strategy Pattern |
| Decorator Pattern | Decorator Pattern |
| Repository Pattern | Repository Pattern |
| Dependency Injection | Dependency Injection |
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
Decorator Pattern
Decorator Pattern
Add responsibilities to objects dynamically.
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"Dependency Injection
Dependency Injection
Invert control by injecting dependencies.
// 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(),
);Factory Pattern
Factory Pattern
Create objects without specifying exact classes.
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)Observer Pattern
Observer Pattern
Define one-to-many dependency for event notification.
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" });Repository Pattern
Repository Pattern
Abstract data access logic.
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)Singleton Pattern
Singleton Pattern
Ensure a class has only one instance with global access.
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)Strategy Pattern
Strategy Pattern
Define family of algorithms and make them interchangeable.
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);#!/bin/bash
# scaffold-tests.sh - Generate test file scaffolding
# Usage: ./scaffold-tests.sh <source_file> [--framework jest|pytest|mocha]
set -euo pipefail
SOURCE_FILE="${{1:?Usage: $0 <source_file> [--framework jest|pytest|mocha]}}"
FRAMEWORK="${{2:-jest}}"
echo "Scaffolding tests for: $SOURCE_FILE (framework: $FRAMEWORK)"
# TODO: Implement test scaffolding logic
# - Parse source file for exported functions/classes
# - Generate test stubs for each export
# - Include setup/teardown boilerplate
# - Add common assertion patterns
echo "Test scaffolding complete."
// Test Template
// TODO: Customize for your testing framework and project
describe('ModuleName', () => {
// Setup
beforeEach(() => {
// TODO: Add test setup
});
afterEach(() => {
// TODO: Add cleanup
});
describe('functionName', () => {
it('should handle the happy path', () => {
// TODO: Add assertion
});
it('should handle edge cases', () => {
// TODO: Add edge case tests
});
it('should handle errors gracefully', () => {
// TODO: Add error handling tests
});
});
});
Related skills
How it compares
Pick design-patterns-implementation over generic refactor prompts when you need pattern-specific guidance tied to SOLID architectural decisions.
FAQ
Which design patterns does design-patterns-implementation cover?
design-patterns-implementation covers Singleton, Factory, Observer, Strategy, and additional patterns with reference guides. The skill maps each pattern to common architectural problems during refactoring or extensible system design.
When should developers invoke design-patterns-implementation?
design-patterns-implementation fits refactoring code architecture, building extensible systems, or enforcing SOLID principles. Use it when structural patterns—not syntax fixes—are the right lever for maintainability.