Fac­to­ry Method is a cre­ation­al design pat­tern that pro­vides an inter­face for cre­at­ing objects in a super­class, but allows sub­class­es to alter the type of objects that will be created.

Problem: Instantiating an object with the new operator creates a dependency on a concrete class, which means high coupling

→The new operator is considered harmful

Solution: Object oriented design goals: low coupling and high cohesionü

→Program against super classes / interfaces rather than against concrete implementations

The Fac­to­ry Method pat­tern sug­gests that you replace direct object con­struc­tion calls (using the new oper­a­tor) with calls to a spe­cial fac­to­ry method. Don’t worry: the objects are still cre­at­ed via the new oper­a­tor, but it’s being called from with­in the fac­to­ry method. Objects returned by a fac­to­ry method are often referred to as prod­ucts.

How can we instantiate new objects without depending on concrete implementations?

<aside>

Applicability

Structure

image.png

  1. Product declares the interface, which is common to all objects produced by the creator and its subclasses

  2. ConcreteProducts are different implementations of the product interface

  3. Creator declares the fac­to­ry method that returns new prod­uct objects. It’s important that the return type of this method match­es the prod­uct interface.

    The code that uses the fac­to­ry method (often called the client code) doesn’t see a dif­fer­ence between the actu­al prod­ucts returned by var­i­ous sub­class­es. The client treats all the prod­ucts as abstract Transport. The client knows that all trans­port objects are sup­posed to have the deliver method, but exact­ly how it works isn’t impor­tant to the client.

    You can declare the fac­to­ry method as abstract to force all sub­class­es to imple­ment their own ver­sions of the method. As an alter­na­tive, the base fac­to­ry method can return some default prod­uct type.

  4. ConcreteCreators override the factory method, so it returns a different type of product

Benefits

Pseudocode

// The creator class declares the factory method that must
// return an object of a product class. The creator's subclasses
// usually provide the implementation of this method.
class Dialog is
  // The creator may also provide some default implementation
  // of the factory method.
  abstract method createButton():Button

  // Note that, despite its name, the creator's primary
  // responsibility isn't creating products. It usually
  // contains some core business logic that relies on product
  // objects returned by the factory method. Subclasses can
  // indirectly change that business logic by overriding the
  // factory method and returning a different type of product
  // from it.
  method render() is
    // Call the factory method to create a product object.
    Button okButton = createButton()
    // Now use the product.
    okButton.onClick(closeDialog)
    okButton.render()

// Concrete creators override the factory method to change the
// resulting product's type.
class WindowsDialog extends Dialog is
  method createButton():Button is
    return new WindowsButton()

class WebDialog extends Dialog is
  method createButton():Button is
    return new HTMLButton()

// The product interface declares the operations that all
// concrete products must implement.
interface Button is
  method render()
  method onClick(f)

// Concrete products provide various implementations of the
// product interface.
class WindowsButton implements Button is
  method render(a, b) is
    // Render a button in Windows style.
	method onClick(f) is
    // Bind a native OS click event.

class HTMLButton implements Button is
  method render(a, b) is
    // Return an HTML representation of a button.
  method onClick(f) is
    // Bind a web browser click event.

class Application is
  field dialog: Dialog

  // The application picks a creator's type depending on the
  // current configuration or environment settings.
  method initialize() is
    config = readApplicationConfigFile()

    if (config.OS == "Windows") then
      dialog = new WindowsDialog()
    else if (config.OS == "Web") then
      dialog = new WebDialog()
    else
      throw new Exception("Error! Unknown operating system.")

  // The client code works with an instance of a concrete
  // creator, albeit through its base interface. As long as
  // the client keeps working with the creator via the base
  // interface, you can pass it any creator's subclass.
  method main() is
    this.initialize()
    dialog.render()

<aside>

How to Implement

  1. Make all prod­ucts fol­low the same inter­face. This inter­face should declare meth­ods that make sense in every product.
  2. Add an empty fac­to­ry method inside the cre­ator class. The return type of the method should match the com­mon prod­uct interface.
  3. In the cre­ator’s code find all ref­er­ences to prod­uct con­struc­tors. One by one, replace them with calls to the fac­to­ry method, while extract­ing the prod­uct cre­ation code into the fac­to­ry method. You might need to add a tem­po­rary para­me­ter to the fac­to­ry method to con­trol the type of returned product. At this point, the code of the fac­to­ry method may look pret­ty ugly. It may have a large switch oper­a­tor that picks which prod­uct class to instan­ti­ate. But don’t worry, we’ll fix it soon enough.
  4. Now, cre­ate a set of cre­ator sub­class­es for each type of prod­uct list­ed in the fac­to­ry method. Over­ride the fac­to­ry method in the sub­class­es and extract the appro­pri­ate bits of con­struc­tion code from the base method.
  5. If there are too many prod­uct types and it doesn’t make sense to cre­ate sub­class­es for all of them, you can reuse the con­trol para­me­ter from the base class in subclasses.
  6. If, after all of the extrac­tions, the base fac­to­ry method has become empty, you can make it abstract. If there’s some­thing left, you can make it a default behav­ior of the method. </aside>

Example