From harness-claude
Provides TypeScript implementations of the Factory Method pattern, including class-based, function-based, and generic registry approaches. Useful for decoupling object creation from client code.
How this skill is triggered — by the user, by Claude, or both
Slash command
/harness-claude:gof-factory-methodThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Define a factory interface that subclasses use to decide which object to instantiate.
Define a factory interface that subclasses use to decide which object to instantiate.
Core structure — Creator declares the factory method, ConcreteCreators override it:
// Product interface
interface Notification {
send(message: string): Promise<void>;
}
// Concrete products
class EmailNotification implements Notification {
constructor(private readonly address: string) {}
async send(message: string): Promise<void> {
console.log(`Email to ${this.address}: ${message}`);
}
}
class SMSNotification implements Notification {
constructor(private readonly phone: string) {}
async send(message: string): Promise<void> {
console.log(`SMS to ${this.phone}: ${message}`);
}
}
// Creator — declares the factory method
abstract class NotificationCreator {
// Factory method — subclasses must implement
abstract createNotification(recipient: string): Notification;
// Template method that uses the factory method
async notify(recipient: string, message: string): Promise<void> {
const notification = this.createNotification(recipient);
await notification.send(message);
}
}
// Concrete creators
class EmailNotificationCreator extends NotificationCreator {
createNotification(recipient: string): Notification {
return new EmailNotification(recipient);
}
}
class SMSNotificationCreator extends NotificationCreator {
createNotification(recipient: string): Notification {
return new SMSNotification(recipient);
}
}
// Client code — depends only on Creator, not ConcreteProduct
async function main(creator: NotificationCreator) {
await creator.notify('[email protected]', 'Your order shipped');
}
Function-based factory (TypeScript idiomatic, no classes needed):
type NotificationType = 'email' | 'sms' | 'push';
function createNotification(type: NotificationType, recipient: string): Notification {
switch (type) {
case 'email':
return new EmailNotification(recipient);
case 'sms':
return new SMSNotification(recipient);
case 'push':
return new PushNotification(recipient);
default:
// Exhaustiveness check — TypeScript will error if a case is missing
const _exhaustive: never = type;
throw new Error(`Unknown notification type: ${type}`);
}
}
Generic factory with registration:
type Constructor<T> = new (...args: any[]) => T;
class NotificationFactory {
private static registry = new Map<string, Constructor<Notification>>();
static register(type: string, ctor: Constructor<Notification>): void {
NotificationFactory.registry.set(type, ctor);
}
static create(type: string, ...args: any[]): Notification {
const Ctor = NotificationFactory.registry.get(type);
if (!Ctor) throw new Error(`Unknown notification type: ${type}`);
return new Ctor(...args);
}
}
NotificationFactory.register('email', EmailNotification);
NotificationFactory.register('sms', SMSNotification);
Factory Method vs. Abstract Factory: Factory Method produces one product via subclass override. Abstract Factory produces families of related products via composition. Start with Factory Method; reach for Abstract Factory when you need a suite of related objects.
Open/Closed Principle in action: Adding a new notification type (SlackNotification) means creating a new ConcreteCreator class — no changes to existing creators or the notify() logic.
Anti-patterns:
if/else logic inside a single create() method that grows indefinitely — use a registry insteadnever type catches missing cases at compile timeWhen to skip the pattern:
new User())refactoring.guru/design-patterns/factory-method
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeApplies the Factory Method pattern to delegate object creation to subclasses or configuration, reducing coupling and enabling extensibility.
Creates objects via factory functions without exposing instantiation logic to callers. Encapsulates complex creation, runtime type selection, and input validation.
Generates DDD-compliant factories for PHP 8.4 domain objects, encapsulating complex creation logic with input validation and unit tests. Ideal for intricate entity instantiation, aggregates, and reconstruction from persistence.