renekton
renekton

Reputation: 61

Why to use Factory method pattern instead of Simple factory

Im trying to understand when to use Factory method pattern compared to Simple factory, I know how each implements but I don't exactly get the point of it.

Let's assume I have client that provides string(name of the car) and based on that string, factory provides object.

I know that method factory satisfies open/closed principle and if I had new car brand for example Mercedes, I would have to edit switch case and add new brand and that would be bad practice. But then with Factory method my factory can't decide on which object to make because there is no switch case. I guess I'm missing a point here. Maybe I should use factory method if I had diffrent logic/strategy on creating car object, maybe one that makes random car object and one that takes string and makes object based on that string.

Also would It be a good practice if I used in Factory Method getCar() function and do some more logic there, like maybe car.tuneEngine() etc. before returning ready to use object?

Simple factory

public class FordCar extends Car {

    public FordCar() {
        super("Ford", "Mondeo", 1.6);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void move() {
        System.out.println("Ford moves");

    }

}

public class CarFactory {

    public Car getCar(String brand) {
        switch (brand) {
        case "ferrari":
            return new FerrariCar();
        case "ford":
            return new FordCar();
        default:
            return null;

        }
    }
}

public class Client {

    public static void main(String[] args) {

        //Simple factory
        CarFactory carFactory = new CarFactory();
        Car clientSimpleCar = carFactory.getCar("ford");
        clientSimpleCar.move();     
    }
}

Factory method pattern

public abstract class CarMethodFactory {

    public Car getCar(){
        Car car = createCar();
        return car;
    }

    public abstract Car createCar();

}

public class FordMethodFactory extends CarMethodFactory{

    @Override
    public Car createCar() {
        return new FordCar();
    }

}

public class Client {

    public static void main(String[] args) {

        CarMethodFactory carMethodFactory = new FordMethodFactory();
        Car clientMethodCar = carMethodFactory.getCar();
        clientMethodCar.move();

    }

}

Upvotes: 3

Views: 4541

Answers (3)

bcperth
bcperth

Reputation: 2291

For learning purposes it might make sense to stay with the GoF definitions of Factory Method and Abstract Factory. GoF is a common point reference and discussion around the basic patterns. Its best to be wary of many of the "examples" found on several advertisement filled sites because some examples are at best misleading.

Sticking with GoF there are 2 factory patterns Factory Method and Abstract Factory.

Simple Factory is not a separate pattern, it is a special case of Factory Method. There is no mention of Simple Factory pattern as a named pattern in Gof. See below.

Factory Method: This does NOT involve a Factory object. It involves Factory methods() as the name suggests.

Example: Consider a base TextEditor class with subclasses for C#, PHP, JS, HTML etc. Each subclass needs its own SyntaxChecker object. The TextEditor base class has an abstract CreateSyntaxChecker() method and each subclass of TextEditor implements CreateSyntaxChecker() interface and returns the specific SyntaxChecker needed by the subclass. Consider pseudo code below for typical use.

Editor = new PHPTextEditor;  // instantiates PHP subclass of  TextEditor
_syntaxChecker = this->CreateSyntaxChecker();     // The constructor of  
PHPTextEditor invokes its over-ridden CreateSyntaxChecker() method, which returns 
the correct PHP SyntaxChecker object.

This complies with GoF Intent of Factory Method. "Define an interface for creating an object, but let subclasses decide which class to instantiate".

"Simple Factory": is a variation of Factory Method. In this variation, using the text editor example, the TextEditor base class has an concrete (instead of abstract) method CreateSyntaxChecker(), which may or not be over-ridden in subclasses, and if not over-ridden, the base class implementation is used.

Abstract Factory: The GoF Intent of Abstract Factory is to "provide an interface for creating families of related or dependent object, without speciifying their concrete classes". What this means in practice is creating an abstract Factory class, whose subclasses define how to create families of related objects.

Example: Extending the TextEditor example, we realise that also need language specific Formatter, and Debug modules in addition to SyntaxChecker. (We could achieve this by multiple applications of Factory Method, but this involves editing several classes). Define an abstract Factory class with 3 abstract methods CreateSyntaxChecker(), CreateDebugger(), CreateFormatter(). Then define subclass PHPFactory, JSFactory, HTMLFactory etc each of which provide implementations for the 3 methods and return the correct object instances.

Consider pseudo code below for typical use.

Factory = new PHPFactory();
Editor = new PHPEditor(Factory);    // Constructor of PHPEditor will invoke the 3 
Factory methods to instantiate the correct versions of the SyntaxChecker, Debugger 
and Formatter objects.

I strongly suggest refactoring your code to comply with the GoF "standard" as a starting point, especially when learning. Later feel free to adapt and adjust to suit your needs, when you are sure of what you are doing :-).

Upvotes: 3

yogi
yogi

Reputation: 31

You can replace switch with enum if you like and simple iteration over list of allowed enum will return your desired object. What i can see from the code is that the first one is using delegation, and the second one couples your client with the concrete factory. I would prefer the first one here.

Upvotes: 0

jaco0646
jaco0646

Reputation: 17164

Factory Method is preferred when inheritance is preferred, because that pattern is implemented through inheritance.

Simple Factory is preferred only when tight coupling is acceptable, because that pattern couples the client to the factory implementation class.

Abstract Factory is preferred when loose coupling is desired, which is almost always.

Upvotes: 0

Related Questions