Skip to main content

Scattered Instantiation

Description​

What does it look like?​

  • Classes are instantiated using new directly and repeatedly throughout the codebase
  • Hard to track which classes are used where, leading to unclear dependencies
  • Instantiation logic is scattered, making management difficult

Why is it a problem?​

  • Results in a fragile design that is hard to modify or replace with new implementations
  • Difficult to unit test (hard to inject mocks)
  • Object creation logic is often copy-pasted in multiple places
  • Instance management becomes tangled like spaghetti code

Bad Example of the Anti-pattern​

class Logger {
log(message: string) {
console.log(`[LOG]: ${message}`);
}
}

class UserService {
private logger: Logger;

constructor() {
this.logger = new Logger(); // ζ―Žε›ž new!!
}

createUser(name: string) {
this.logger.log(`γƒ¦γƒΌγ‚ΆγƒΌδ½œζˆ: ${name}`);
}
}

Issues:​

  • Logger is instantiated directly inside UserService
  • Other services may also repeat new Logger(), leading to duplication
  • Difficult to reuse the logger logic as a shared component

Refactoring by Pattern​

Design patterns that can address this​

PatternOverviewMain Refactoring Approach
Factory MethodDelegate object creation to a subclassMake instantiation logic extensible
Abstract FactoryGroup related objects into a factoryAbstract creation logic for easy switching
BuilderClarify complex creation stepsSeparate construction steps for clarity
SingletonRestrict to a single instance and reuse itUseful for shared global state