Navigation:  Appendix B: Dolphin Pattern Book > Method Patterns >

Factory Method

Previous pageReturn to chapter overviewNext page

Context

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

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 #newXXX, where XXX 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 method on an instance basis or a class basis. Better still, the factory class method should not hard-code the class name at all but, instead, should request the class name from a Constant Access Method.

Examples

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 as follows:

LotterySyndicate>>initialize

      "Initialize the receiver."

      participants := Set new.

 

Using a factory method 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 better still:

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 CommandQuery implements a method, #newCommandQuery: which is a factory method that allows the creation of query objects. Note that this also uses a Constant Access Method to obtain the actual class to use for the instantiation.

CommandQuery>>newCommandQuery: action

  "Answer a new <CommandQuery> for the <commandDescription>, action,

  originating in the receiver's source <View>."

  ^self commandQueryClass

      commandDescription: action

      source: self source

 

CommandQuery>>commandQueryClass

  "Answer the class of <CommandQuery> to use for querying the status of commands."

  ^CommandQuery

 

Related Patterns

Abstract Factory