Pattern: Factory


Context

It is often necessary, in a method, to create a new instance of some class. If the instance creation is hard-coded, then programmers of subclasses will not be able to substitute a different class of the object.

Solution

Implement a Factory instance method whose sole purpose is to instantiate and answer the new object. Subclasses can then override this method and create an object of their own choice.

The selector for a Factory method should be of the form #newXxxxxx, where.Xxxxxx is a description (not the class) of the resultant object.

For greater flexibility, make the Factory instance method call a Factory class method of the same name. This allows the programmer of a subclass to override the Factory method on an instance basis or a class basis. Better still, the Factory class method should not hard-code the class name, but instead, should request the class name from a Constant Access Method which answers the value of a class variable.

Example

Consider an imaginary class LotterySyndicate with two instance variables participants (a collection of people who are members of the syndicate) and winningsSoFar (the total value of winnings so far).

Instead of hard-coding the class of participants:

LotterySyndicate>>initialize
        "Initialize the receiver."

        participants := Set new.
        ...
We would write:
LotterySyndicate>>initialize
        "Initialize the receiver."

        participants := self newParticipants.
LotterySyndicate>>newParticipants
        "Answer a new participants collection." 

        ^Set new
or:
 
LotterySyndicate>>initialize
        "Initialize the receiver."

       participants := self newParticipants.
LotterySyndicate>>newParticipants
        "Answer a new participants collection." 

        ^self class newParticipants
LotterySyndicate class>>newParticipants
        "Answer a new participants collection." 

        ^Set new
or: 
LotterySyndicate>>initialize
        "Initialize the receiver."

        participants := self newParticipants.

LotterySyndicate>>newParticipants
        "Answers a new participants collection." 

        ^self class newParticipants

LotterySyndicate class>>newParticipants
        "Answers a new participants collection." 

        ^self participantClass new

LotterySyndicate class>>participantClass
        "Answers the class to use for the participants collection." 

        ^Set 

Known Uses

The class CommonDialog uses a Factory method to create a structure for communicating with the underlying Common Dialog.

CommonDialog>>initialize
	"Private - Initialize the receiver"

	winStruct := self winStructClass new.
	super initialize.
CommonDialog>>winStructClass
	"Private - Answer the class to use for the receiver's associated windows parameter structure."

	^self subclassResponsibility
ColorDialog>>winStructClass
	"Private - Answer the class to use for the receiver's associated windows parameter structure."

	^CHOOSECOLOR

Related Patterns