Factory Pattern

CSC-430

Phillip Wright

OO Principle: Dependency Inversion

Depend upon abstractions. Do not depend on concrete classes.

Dependency Inversion

  • Both high level and low level classes should depend on abstractions.
  • Variables should not reference concrete classes
    • Which means we can’t use new!
  • Classes should not derive from concrete classes
  • Methods should not override base class implementations

…for some definition of “should”

DI and Factories

With past patterns, we have been abstracting and encapsulating behavior, dependencies, etc. and making them runtime properties, increasing extensibility, etc.

To eliminate coupling introduced by the new operator, we will now abstract and encapsulate object instantiation using factories.

The Factory Method Pattern

Defines an interface for creating an object, but let’s subclasses decide which class to instantiate. The Factory Method Pattern lets a class defer instantiation to a subclass.

AKA: Virtual Constructor

Example

public interface Product{
  // ...
}

public class Car implements Product{
  // ...
}

public class Boat implements Product{
  // ...
}

Example II

public abstract class Producer{
  public Product produce(){
    Product p = createProduct();
    // do stuff with product
    return p;
  }

  protected abstract Product createProduct();
}

Note that the Producer only has dependencies on the Product interface, just like the Car and Boat classes. This class can now be closed for modification since we have inverted our dependencies.

Example III

public CarProducer extends Producer{
  protected Product createProduct(){
    return new Car();
  }
}

public BoatProducer extends Producer{
  public Product createProduct(){
    return new Boat();
  }
}

Factory Method

  • Eliminates the need to bind application specific classes in code
  • Allows us to close our classes to modification
  • Concentrates instantiation into fewer locations

Isolating Problems

A common goal of good design is to simply take the bad stuff you can’t eliminate from your code entirely, and isolate it in the smallest number of locations possible. This applies to:

  • object instantiation
  • side effects
  • instanceof testing

When to use

  • When a class can’t anticipate the class of objects it must create
  • When a class wants to delegate object instantiation to subclasses

Warning

If the only thing the subclass does is instantiate an object, then maybe we’re just making our lives more difficuly for no reason.

If you are already subclassing, though, then it’s fine.

Abstract Factory Pattern

Provides an interface for creating families of related or dependent objects without specifying their concrete classes.

Abstract Factory Pattern II

  • Isolates concrete classes
  • Makes it easy to exchange families of classes
  • Promotes consistency

When To Use

  • A system should be independent of how its products are created
  • A system should be configured with one of multiple families of products
  • A family of products must be used together
  • You want to provide a library of products without exposing their implementation

Warning

If we need to add a new type of product, it can be difficult, because all product families must be updated.