minizibi
minizibi

Reputation: 671

Creator in Factory Method Pattern

source: https://en.wikipedia.org/wiki/Factory_method_pattern

source: https://en.wikipedia.org/wiki/Factory_method_pattern

This diagram really alludes to Factory Method Pattern?

Why do we need Creator? Look at code example:

 interface Product{
    public String getName();
}

class ConcreteProduct1 implements Product {    
    @Override
    public String getName() {
        return "I'm product 1";
    }       
}

class ConcreteProduct2 implements Product {    
    @Override
    public String getName() {
        return "Im product 2!";
    }   
}

// CREATOR HERE

interface Creator{
    public Product createProuct(String productClass);
}

class ConcreteCreator implements Creator{    
    @Override
    public Product createProuct(String productClass) {
            if(productClass.equals("1"))
                return new ConcreteProduct1();
            else if(productClass.equals("2"))
                return new ConcreteProduct2();
            else
                return null; //
        }
    }    

public class Test {     
    public static void main(String[] args) {
        Creator c = new ConcreteCreator();          
        Product product = c.createProuct("1");          
        System.out.print(product.getName());
    }
}

Code without Creator interface:

class ConcreteCreator{
    public Product createProuct(String productClass) {
            if(productClass.equals("1"))
                return new ConcreteProduct1();
            else if(productClass.equals("2"))
                return new ConcreteProduct2();
            else
                return null; //
        }
    }

public class Test{      
    public static void main(String[] args) {            
        ConcreteCreator c = new ConcreteCreator();          
        Product product = c.createProuct("1");          
        System.out.print(product.getName());
    }
}

So why do we need Creator interface? Is it in case i would add another factory method in future? If yes, is it still Factory Method Pattern or Abstract Factory Pattern? Could you give me some code examples with extensions to my Creator interface and implementation of ConcreteCreator which uses two methods?

Also how about generic Creator? It looks much simpler than many type specified Creators...:

interface Product{
    public String getName();
}

class ConcreteProduct implements Product{    
    @Override
    public String getName() {
        return "I'm product 1";
    }
}

interface Moveable{
    public String move();
}

class Car implements Moveable{    
    @Override
    public String move() {
        return "moving...";
    }
}

interface Creator<T>{
    public T create();
}

class ConcreteCreatorProducts implements Creator<Product>{
    @Override
    public Product create() {
        return new ConcreteProduct();
    }
}

class ConcreteCreatorCar implements Creator<Car>{    
    @Override
    public Car create() {
        return new Car();
    }
}

public class Test{      
    public static void main(String[] args) {
        Creator<Product> productCreator = new ConcreteCreatorProducts();
        Product product = productCreator.create();
        Creator<Car> carCreator = new ConcreteCreatorCar();
        Car car = carCreator.create();
    }
}

Upvotes: 3

Views: 1334

Answers (2)

fgb
fgb

Reputation: 18559

In your example, you don't need a Creator interface, unless you want to have multiple implementations and swap between them. But the diagram is actually describing a slightly different pattern than you've implemented.

The way the factory method pattern is described there is based on the original design patterns book. It's a bit odd today, as it uses subclassing to configure a class, when we would encourage the use of composition instead. So, the diagram does show the factory method pattern, but different from the way it's described in many other places.

The factory method pattern is:

Define an interface for creating an object, but let subclasses decide which class to instantiate. The Factory method lets a class defer instantiation it uses to subclasses.

  • In the original pattern, Creator isn't an interface. By 'interface', they mean the factory method that Creator defines, not interfaces like Java has.

  • The factory method doesn't need a parameter. Instead of different types being returned based on the parameter, there are different types returned based on the subclass created.

  • Also, you wouldn't call createProduct from main, but from methods within Creator. Creator is the user of the factory method, so it defines a factory method, that may be abstract, and some other methods that use that method.

See the Java examples on the wikipedia page. The MazeGame class is the Creator. The constructor is used as the anOperation method, and there are multiple subclasses for creating different kinds of rooms.

Upvotes: 1

GhostCat
GhostCat

Reputation: 140553

Code is written so that human readers understand it.

This means that you as a programmer sometimes use the means of the language not because it is absolutely mandatory, but because it is the best way to communicate your intention.

As soon as you declare that something is an interface you make it clear that there is no "base class" - only an interface, and that any specific implementation is subtle detail not really important to people dealing with the corresponding objects.

In other words: yes, it is perfectly possible to implement a factory pattern where the part responsible for creating the actual objects is not an interface, but a fixed class. Especially when thinking about "internal" factories (that are not exposed to a public API and wide range of "different" end users) that case is probably even the more common approach. ( the code I write contains many factories, few of them would follow the above approach of "interfacing" almost everything )

Beyond that - keep in mind that programming is also often about balancing between different requirements. Example: you might (again for communicating intent) decide to declare a class that provides a certain functionality as final. So that nobody gets idea of extending that specific class. But doing so means that users of that API are all of a sudden affected in their choice of mocking frameworks. As mocking final classes is not something that you can do easily. When you are then consuming this API, and you want to write unit tests - then you are very happy about the fact that the public API is relying on interfaces, not classes. Because you can always mock interfaces - but as said, final classes can cause headache.

Upvotes: 0

Related Questions