0. Overview
Factory Pattern is primarily divided into three categories: Simple Factory Pattern, Factory Method Pattern, and Abstract Factory Pattern. All of them are classified as Creational Design Pattern, although the Simple Factory Pattern is not included in the GoF’s 23 design patterns.
Definition of Factory Pattern: It defines a factory interface for creating product objects, delegating the actual creation of these product objects to specific subclasses of the factory. This satisfies the characteristic of “separating creation from usage”, as required by Creational Design Pattern.
1. Simple Factory Pattern
Simple Factory Pattern, also known as the Static Factory Method Pattern, uses a single factory object to determine which type of product instance to create. Essentially, the Simple Factory Pattern relies on a factory class that dynamically decides which product class to instantiate based on the parameters provided (such as product type).
Pros:
- A single factory class provides access to all different product types, making the structure straightforward, easy to implement, and easy to understand.
- The client does not need to know the specific class name of the product being created. Instead, by simply passing the correct parameter (such as the product type), the client can obtain the desired object without needing to know the details of its creation.
Cons:
- The factory class is centralized, with heavy responsibilities; adding new products requires modifying the factory’s logic (making it hard to extend), which violates the Open-Closed Principle.
- The factory uses a static method to create products, preventing the formation of an inheritance-based hierarchy for the factory role.
Scenarios:
- When the factory class is responsible for creating a limited number of product types.
- When the client only needs to pass parameters to the factory class and does not need to know the logic or details of object creation.
1.1. Structure and Implementation
The main roles in the Simple Factory Pattern are as follows:
- Simple Factory (SimpleFactory): This is the core of the Simple Factory Pattern, responsible for the internal logic to create all products. The factory class provides a public static method for creating products, which can be called directly from outside. This method uses a product type parameter to create the desired product object.
- Abstract Product (IProduct): This is the parent interface for all product objects created by the simple factory, defining the common interface for all product instances.
- Concrete Products (Phone, Laptop, Earphone): These are the specific products targeted by the Simple Factory, each implementing the common product interface.
The class diagram is as follows:
1.2. Code Example
Product Interface and Concrete Product Classes:
1 | public interface IProduct { |
The factory class in the Simple Factory Pattern is responsible for creating various products and providing a unified public product interface for returning them.
1 | public class SimpleFactory { |
Usage of the Simple Factory:
1 | public class SimpleFactoryMain { |
Execution Result:
1 | I am a phone. |
2. Factory Method Pattern
Factory Method Pattern, also known as the Polymorphic Factory Pattern, is a creational pattern classified among the three major categories of design patterns. It defines an interface for creating objects, but the subclasses determine which class to instantiate, meaning the Factory Method Pattern defers instantiation to the subclasses.
Compared to 1. Simple Factory Pattern, the core factory class no longer handles the creation of all products; instead, it delegates the actual work (such as creating products) to specific subclasses. The core factory class becomes an abstract factory role, which only defines the public interface that concrete factory subclasses must implement, without handling the specific details of any particular product.
Pros:
- Users only need to concern themselves with the factory corresponding to the desired product to obtain the necessary product, without worrying about the specific creation logic of the product.
- When new products are added, only the corresponding factory class needs to be added, providing good extensibility and adhering to the Open-Closed Principle.
Cons:
- As the number of products increases, it can lead to a proliferation of classes, increasing complexity and making the system harder to understand.
- The abstract product can only produce one type of product; this issue can be resolved using the Abstract Factory Pattern.
Scenarios:
- The client only knows the factory name corresponding to the product and not the specific product names, such as Phone Factory, Laptop Factory, etc.
- The task of creating objects is completed by one of several concrete subclasses, while the abstract factory only provides the interface for creating products.
- The client is not concerned with the details of product creation but only cares about the production factory.
- When you need a laptop, you can directly obtain it from the factory that produces laptops, without needing to know how the laptop is manufactured or the specific implementation of that laptop.
2.1 Structure and Implementation
The main roles in the Factory Method Pattern are as follows:
- Abstract Factory (IFactory): Provides the interface for creating products, allowing the caller to access the specific factory’s factory method
createProduct()
to create products. - Concrete Factories (PhoneFactory, LaptopFactory, EarphoneFactory): Implement the methods defined in the abstract factory, completing the creation of specific products.
- Abstract Product (IProduct): Defines the specifications for the product, describing the main characteristics and functionalities of the product.
- Concrete Products (Phone, Laptop, Earphone): Implement the interfaces defined by the abstract product role and are created by specific factories, corresponding one-to-one with the concrete factories.
The class diagram is as follows:
2.2 Code Example
Product Interface and Concrete Product Classes:
1 | public interface IProduct { |
Abstract Factory Interface and Its Concrete Factories:
1 | // abstract factory interface |
Usage of the Factory Method Pattern:
1 | public class FactoryMethodMain { |
Execution Result:
1 | I am a phone. |
3. Application in Source Code
3.1. JDK-java.util.Calendar (Simple Factory Pattern)
1 | // java.util.Calendar |
In the createCalendar()
static method, the Calendar
class returns different subclass instances based on conditional checks, involving the following concrete subclasses:
3.2. JDK-java.text.NumberFormat (Simple Factory Pattern)
1 | // java.text.NumberFormat |
The getInstance()
static method in NumberFormat
generates different subclass instances of NumberFormat
based on the provided locale
parameter. By default, it calls sun.util.locale.provider.NumberFormatProviderImpl#getInstance
to create a new java.text.DecimalFormat
instance, applying specific formatting settings as required, such as currency format, percentage format, and others.
3.3. JDK-java.net.URLStreamHandlerFactory (Factory Method Pattern)
The URLStreamHandlerFactory
interface (abstract factory) defines a factory for URL stream protocol handlers, serving as a common base for all stream protocol handlers. Stream protocol handlers understand how to establish connections for specific protocol types, such as HTTP or HTTPS.
The URLStreamHandler
abstract class acts as an abstract product, where instances of its subclasses (concrete products) are not created directly by the application. Instead, they are managed and created by classes that implement the URLStreamHandlerFactory
factory interface (concrete factories).
Abstract Factory and Its Subclasses (Concrete Factories):
1 | // abstract factory |
Abstract Product and Its Subclasses (Concrete Products):
1 | // abstract product |
The specific subclasses of the URLStreamHandler
abstract product are shown in the red box in the figure below:
3.4. slf4j-org.slf4j.ILoggerFactory (Factory Method Pattern)
Abstract Factory and Its Concrete Factories are as follows:
1 | // abstract factory |
Abstract Product and Its Concrete Products are as follows:
1 | // abstract product |
3.5. JDK-javax.xml.bind.JAXBContext (Factory Method Pattern)
Abstract Factory and Its Concrete Factories are as follows:
1 | // abstract factory |
Abstract Product and Its Concrete Products are as follows:
1 | // abstract product |
3.6. Iterator-java.util.Collection (Factory Method Pattern)
Abstract Factory and Its Concrete Factories are as follows:
1 | // abstract factory |
Abstract Product and Its Concrete Products are as follows:
1 | // abstract product |