does a factory just return an implementation of an interface? Is that the job?
From Wiki:
The essence of the Factory Pattern is to "Define an interface for creating an object, but let the subclasses decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses.
In essence, yes.
However, depending on your language, "interface" may have a specific meaning. A factory typically returns a concrete implementation of a general contract - which can be an interface, a base class, or any other means of specialization.
Also, there are times when a factory returns the exact type you're specifying - but you use a factory for another purpose, such as managing lifetime, tracking, or some other rationale other than construction of a specialized type.
Couple more great resources on this:
The more specific answer is that a Factory is to provide pre-initialization and pre-construction work for types of objects which are common. The simplest example (I have seen) of this is a "Hammer factory", where the hammer is constructed of two objects (handle, and head) and is given a single name "wood handled claw hammer". Our factory can therefore have a single method:
(Hammer|IHammer|...) GetHammer(string hammername);
Which can return one of several objects (an actual Hammer Object, an Interface describing the Hammer, a Base class for Hammer, etc). Possibly the most useful of these is to return an Interface which describes the hammer and allows us to implement a number of useful design patterns from there.
Sometimes that's all a factory does, but they can do a lot more:
Choose a concrete implementation based on data that's only available at run-time:
// Beverage Factory public IBeverage CreateBeverage(DateTime orderDate) { return orderDate.Hour > 12 ? new Beer() : new Milk(); }
Perform post-construction initialization (often expensive initialization or initialization of data that's not appropriate to encapsulate within the object itself):
// Weather report factory public IWeatherReport CreateWeatherReport() { WeatherReport report = new WeatherReport(); report.data = WeatherWebService.GetData(); return report; }
Initialize the new instance based on an existing instance:
// Fittest Algorithm Factory public Algorithm CreateNewAlgorithm() { return this.fittestAlgorithm.Clone(); }
Draw an instance from a pool instead of creating one from scratch:
public IDbConnection CreateConnection(string connectionString) { return this.ConnectionStacks[connectionString].Pop(); }
Return a singleton instance (though yuck, and you'd better be sure it's thread safe!)