# Factory MethodA intermediate-level guide to Factory Method: before-and-after java code and diagrams for a CS student.

## The "New" Keyword Trap

When you start building features, it often feels natural to instantiate objects exactly where you need them. If your program needs a `WordDocument`, you write `new WordDocument()`. This works fine until your requirements grow. Suddenly, your editor needs to handle PDFs too. Then, perhaps, Excel files or HTML files.

Soon, your core logic becomes cluttered with conditional checks to decide which specific class to instantiate. This is a "Switch Statements" code smell—a type-dispatching conditional that creates tight coupling. Coupling describes the strength of the link between two components; here, `DocumentEditor` is so tightly coupled to concrete types like `WordDocument` and `PdfDocument` that it cannot function without knowing they exist.

```java
interface Document {
    void open();
}

class WordDocument implements Document {
    public void open() { System.out.println("Opening Word document..."); }
}

class PdfDocument implements Document {
    public void open() { System.out.println("Opening PDF document..."); }
}

class DocumentEditor {
    // Problem: The editor is tightly coupled to concrete implementations.
    // Adding a new document type requires modifying this switch block.
    public Document createDocument(String type) {
        if (type.equals("WORD")) {
            return new WordDocument();
        } else if (type.equals("PDF")) {
            return new PdfDocument();
        }
        throw new IllegalArgumentException("Unknown type: " + type);
    }
}
```

In this design, every time a new document type is added to the system, you are forced to modify the `createDocument` method in `DocumentEditor`. This violates the Open-Closed Principle, which suggests software entities should be open for extension but closed for modification. The editor "knows" too much about the specific implementation details of every possible document type.

```mermaid
classDiagram
    class Document {
        <<interface>>
        +open() void
    }
    class WordDocument {
        +open() void
    }
    class PdfDocument {
        +open() void
    }
    class DocumentEditor {
        +createDocument(String) Document
    }

    WordDocument ..|> Document
    PdfDocument ..|> Document
    DocumentEditor ..> WordDocument : dependency
    DocumentEditor ..> PdfDocument : dependency
```

## Delegating Creation with the Factory Method

To fix this, we use a creational design pattern called the **Factory Method**. Instead of the `DocumentEditor` deciding which object to create using a switch statement, we delegate that responsibility to its subclasses.

The "Factory Method" is actually an abstract method (or an empty placeholder) defined in a base class. The base class handles the high-level logic, but it leaves the actual instantiation to the subclasses via this method. This allows the core business logic to remain completely independent of the specific products being created.

```java
interface Document {
    void open();
}

class WordDocument implements Document {
    public void open() { System.out.println("Opening Word document..."); }
}

class PdfDocument implements Document {
    public void open() { System.out.println("Opening PDF document..."); }
}

abstract class DocumentEditor {
    // The Factory Method: delegating instantiation to subclasses.
    protected abstract Document createDocument();

    public void edit() {
        Document doc = createDocument();
        doc.open();
    }
}

class WordEditor extends DocumentEditor {
    @Override
    protected Document createDocument() {
        return new WordDocument();
    }
}

class PdfEditor extends DocumentEditor {
    @Override
    protected Document createDocument() {
        return new PdfDocument();
    }
}
```

In the refactored version, `DocumentEditor` is now an abstract class. It defines a "hook" called `createDocument()`. Notice that the `edit()` method no longer cares if it is working with a Word or PDF file; it simply calls `createDocument()` and then tells the resulting object to `open()`.

The actual decision of *which* document to create has moved down the inheritance hierarchy. The `WordEditor` subclass implements the factory method by returning a `WordDocument`, while the `PdfEditor` does the same for PDF files.

```mermaid
sequenceDiagram
    participant E as WordEditor
    participant DE as DocumentEditor
    participant D as WordDocument

    E ->> DE: edit()
    DE ->> E: createDocument()
    E -->> DE: return new WordDocument()
    DE ->> D: open()
```

## Why It Works: Breaking the Link

The primary benefit of this pattern is that it breaks the direct dependency between the high-level logic and the low-level concrete classes. The `DocumentEditor` now only depends on the `Document` interface. 

By using inheritance to handle creation, you achieve "Replace Conditional with Polymorphism." Instead of a switch statement checking a string to decide which path to take, the program uses the specialized behavior of the subclass itself to drive the logic. This makes your system more extensible; adding a new document type simply involves creating one new class for the product and one new creator subclass, without ever touching your existing, tested editor logic.

```mermaid
classDiagram
    class Document {
        <<interface>>
        +open() void
    }
    class WordDocument {
        +open() void
    }
    class PdfDocument {
        +open() void
    }
    class DocumentEditor {
        <<abstract>>
        #createDocument()* Document
        +edit() void
    }
    class WordEditor {
        #createDocument() Document
    }
    class PdfEditor {
        #createDocument() Document
    }

    WordDocument ..|> Document
    PdfDocument ..|> Document
    DocumentEditor <|-- WordEditor
    DocumentEditor <|-- PdfEditor
    WordEditor ..> WordDocument : creates
    PdfEditor ..> PdfDocument : creates
```

## When to Use It, and When Not To

The Factory Method is powerful, but it is not a silver bullet. 

**Use it when:**
* You want to provide users of your library or framework with a way to extend its internal components.
* Your core logic needs to work with various objects, but you don't know the exact types until runtime or at compile time through subclassing.

**Avoid it when:**
* The creation logic is extremely simple and unlikely to ever change; adding more classes just adds "boilerplate" (extra, repetitive code) that increases complexity without providing real value.
* You find yourself creating a new subclass for every single tiny variation of an object's behavior, leading to a massive explosion of subclasses.

## Takeaways

- Use the Factory Method to move instantiation responsibility from a parent class to its subclasses.
- This pattern helps eliminate "Switch Statements" that are used solely to decide which `new` keyword to call.
- Refactoring toward this pattern helps adhere to the Open-Closed Principle by allowing new types to be added without modifying existing code.

## Usage

**The client uses a specific subclass to get the desired behavior without manual type checking.**

```java
DocumentEditor editor = new WordEditor();
editor.edit();
```
