Suggest an editImprove this articleRefine the answer for “What is Factory design pattern?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**Factory design pattern** - a creational pattern that centralizes object creation behind a function or method. Callers pass a type; the factory decides which class to instantiate. ```javascript const notif = NotificationFactory.create('email', 'Hi!'); notif.send(); ``` **Key point:** use it when the object type depends on runtime data or when you need to swap implementations without changing caller code.Shown above the full answer for quick recall.Answer (EN)Image**Factory design pattern** - a creational pattern that puts object creation behind a function or method, so calling code never needs to use `new` directly on concrete classes. ## Theory ### TL;DR - Factory wraps `new` in one place; callers ask for an object by type, not by class name - Useful when the object type depends on runtime data: a config string, a user role, an environment flag - Three forms: Simple Factory (one static method), Factory Method (subclass overrides `create()`), Abstract Factory (family of related objects) - Trade-off: Simple Factory requires edits when you add a new type; Factory Method solves that with subclasses ### Quick example ```javascript // Without factory - caller knows every concrete class const user = role === 'admin' ? new AdminUser(data) : new RegularUser(data); // With factory - caller only knows the factory const user = UserFactory.create(role, data); ``` ### How Simple Factory works A Simple Factory is a static method (or a plain function) that takes a type string and returns the matching object. No concrete class leaks out to the caller. ```javascript class NotificationFactory { static create(channel, message) { switch (channel) { case 'email': return new EmailNotification(message); case 'sms': return new SMSNotification(message); case 'push': return new PushNotification(message); default: throw new Error(`Unknown channel: ${channel}`); } } } const notif = NotificationFactory.create('email', 'Hello!'); notif.send(); // EmailNotification handles this ``` The `switch` lives in one file. Adding a new channel means changing one class, not hunting through the codebase. ### Factory Method pattern Simple Factory is a popular convention but is not in the original Gang of Four book. Factory Method is the actual GoF pattern. A base class defines a method like `createProduct()`, and each subclass overrides it to return a different object type. ```javascript class Dialog { createButton() { throw new Error('createButton must be implemented'); } render() { const button = this.createButton(); // factory method button.onClick(() => this.closeDialog()); button.render(); } } class WindowsDialog extends Dialog { createButton() { return new WindowsButton(); } } class WebDialog extends Dialog { createButton() { return new HTMLButton(); } } ``` The `render()` method in the base class works with any button type. You add a new platform by adding a new subclass, not by editing `Dialog`. ### When to use - The type of object to create comes from a config value, a user selection, or an environment variable - You want to swap implementations without touching the caller (handy in tests: the factory returns a mock, the real code never changes) - Several classes share an interface but differ in behavior - You're writing a library and consumers should be able to plug in their own implementations In practice, the clearest signal is when calling code already has an `if/else` or `switch` to pick a class. That logic belongs in a factory, not scattered across features. Don't add a factory just because you have two classes. If you always create the same type, `new` is the right call. ### Common mistakes **Mistake 1: A factory that never branches** ```javascript // Pointless indirection class UserFactory { static create(data) { return new User(data); // always the same class } } ``` If there is no branching, there is no reason for a factory. **Mistake 2: Objects with inconsistent interfaces** ```javascript class AnimalFactory { static create(type) { if (type === 'dog') return new Dog(); // has .bark() if (type === 'cat') return new Cat(); // has .meow() // caller still has to check the type - factory helps nothing } } ``` All objects from a factory should share the same interface. If `Dog` and `Cat` have different APIs, the caller is back to checking types manually. **Mistake 3: No default case** ```javascript static create(type) { switch (type) { case 'admin': return new AdminUser(); case 'guest': return new GuestUser(); // no default - returns undefined silently } } ``` Always throw on an unknown type. Silent `undefined` causes confusing bugs downstream. **Mistake 4: Treating Simple Factory and Factory Method as the same thing** They are different. Simple Factory is a helpful convention. Factory Method is a formal GoF pattern built on subclass inheritance. In interviews, ask which one the question is about before answering. ### Real-world usage - React: `React.createElement()` is a factory function. Pass a string or component class, get back a virtual DOM element. - Node.js `http`: `http.createServer()` wraps the constructor and returns a Server instance. - Express: `express()` is a factory that returns an Application object. - Jest: `jest.fn()` returns a configured mock function. - Angular DI: the injector uses factory functions to create service instances. ### Follow-up questions **Q:** What is the difference between Simple Factory and Factory Method? **A:** Simple Factory is a static method or function that picks a class and calls `new`. Factory Method is a GoF pattern where a base class defines a method that subclasses override to produce objects. With Simple Factory you edit one file to add a type; with Factory Method you add a new subclass. **Q:** How does Factory relate to Abstract Factory? **A:** Abstract Factory produces families of related objects. Instead of one factory making one type, you have a factory interface with several creation methods. A `WindowsUIFactory` creates `WindowsButton` and `WindowsScrollbar` together. Use it when objects need to be consistent with each other. **Q:** Can you write a factory without a class? **A:** Yes. A plain function works fine. `function createUser(role, data) { ... }` is a factory. The class adds nothing here except a namespace. Many JavaScript codebases prefer plain factory functions over static class methods. **Q:** How does Factory help with testing? **A:** You inject the factory as a dependency instead of calling `new` directly in business logic. In tests, you pass a fake factory that returns mocks. The code under test never knows the difference. **Q:** When would you pick Factory Method over Simple Factory? **A:** When new types appear often, or when external code should be able to define new types without touching your source. Factory Method allows extension without modification. ## Examples ### Basic: shape creation ```javascript class Circle { constructor(radius) { this.radius = radius; } area() { return Math.PI * this.radius ** 2; } } class Rectangle { constructor(w, h) { this.width = w; this.height = h; } area() { return this.width * this.height; } } function createShape(type, ...args) { if (type === 'circle') return new Circle(...args); if (type === 'rectangle') return new Rectangle(...args); throw new Error(`Unknown shape: ${type}`); } const shapes = [ createShape('circle', 5), createShape('rectangle', 4, 6), ]; shapes.forEach(s => console.log(s.area())); // 78.53... // 24 ``` Both shapes have `.area()`. The `forEach` loop works without knowing the concrete type behind each object. ### Middle: payment processor ```javascript class StripeProcessor { pay(amount) { console.log(`Stripe: charging $${amount}`); } } class PayPalProcessor { pay(amount) { console.log(`PayPal: sending $${amount}`); } } class CryptoProcessor { pay(amount) { console.log(`Crypto: transferring $${amount} in BTC`); } } class PaymentFactory { static create(method) { const map = { stripe: StripeProcessor, paypal: PayPalProcessor, crypto: CryptoProcessor, }; const Processor = map[method]; if (!Processor) throw new Error(`Unsupported method: ${method}`); return new Processor(); } } // method comes from user selection at checkout const processor = PaymentFactory.create(getUserSelectedMethod()); processor.pay(99.99); ``` The checkout flow imports one factory, not three processor classes. Replacing Stripe with another provider means one line changes inside `PaymentFactory`, nothing else. ### Senior: factory with self-registration ```javascript class PluginFactory { static #registry = new Map(); static register(name, Constructor) { this.#registry.set(name, Constructor); } static create(name, ...args) { const Constructor = this.#registry.get(name); if (!Constructor) throw new Error(`Plugin "${name}" not registered`); return new Constructor(...args); } } // Core plugins register on startup PluginFactory.register('logger', LoggerPlugin); PluginFactory.register('cache', CachePlugin); // A third-party plugin extends the system without touching PluginFactory PluginFactory.register('analytics', AnalyticsPlugin); const logger = PluginFactory.create('logger', { level: 'debug' }); ``` No `switch` statement to edit. New types register themselves. This pattern appears in Webpack loaders, Babel plugins, and similar extensible systems.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.