Factory mode can be divided into three modes: simple factory, factory method and abstract factory
Usage scenario
Generally speaking, there are two usage scenarios of factory mode:
- The creation process of a single object is complex, such as an object that needs complex initialization operations
- You need to create different objects according to different types
For the three modes of subdivision, the use scenarios can be distinguished:
- When the object creation logic is simple, you usually only need to create new. At this time, you can consider the simple factory mode
- When the object creation logic is very complex and various initialization operations need to be done, consider using the factory method mode to split the complex logic of object creation into various factory classes, so that each factory class will not be too complex
- When there is more than one product family in the system and only one product family is used at a time, the abstract factory pattern is used
Simple factory mode
Class diagram
ProcuctA and ProductB inherit the Product abstract class, and ProductFactory returns different Product instances according to the passed in type
code implementation
Product
public abstract class Product { public abstract void use(); }
ProductA
public class ProductA extends Product { @Override public void use() { System.out.println("You are using ProductA..."); } }
ProductB
public class ProductB extends Product { @Override public void use() { System.out.println("You are using ProductB..."); } }
ProductFactory
public class ProductFactory { public Product createProduct(String type) { Product product = null; if ("A".equals(type)) { product = new ProductA(); } else if ("B".equals(type)) { product = new ProductB(); } return product; } }
Main
public class Main { public static void main(String[] args) { ProductFactory factory = new ProductFactory(); Product product; product = factory.createProduct("A"); product.use(); product = factory.createProduct("B"); product.use(); } }
comment
When adding different products frequently, you need to frequently modify the if/else logic in the ProductFactory
application
JDK
java.text.DateFormat#getDateInstance() java.text.DateFormat#getDateInstance(int) java.text.DateFormat#getDateInstance(int, java.util.Locale)
Encryption class to obtain key generators of different encryption algorithms:
KeyGenerator keyGen=KeyGenerator.getInstance("DESede");
Factory method model
Class diagram
Compared with a simple factory, this method defines the ProductFactory as an abstract class, and then creates different specific productafactories and productbfctories. It determines which factory and object to create during use, avoiding if/else judgment
code implementation
Product
public abstract class Product { public abstract void use(); }
ProductA
public class ProductA extends Product { @Override public void use() { System.out.println("You are using ProductA..."); } }
ProductB
public class ProductB extends Product { @Override public void use() { System.out.println("You are using ProductB..."); } }
ProductFactory
public abstract class ProductFactory { public abstract Product createProduct(); }
ProductAFactory
public class ProductAFactory extends ProductFactory { @Override public Product createProduct() { return new ProductA(); } }
ProductBFactory
public class ProductBFactory extends ProductFactory { @Override public Product createProduct() { return new ProductB(); } }
Main
public class Main { public static void main(String[] args) { ProductFactory factory; Product product; factory = new ProductAFactory(); product = factory.createProduct(); product.use(); factory = new ProductBFactory(); product = factory.createProduct(); product.use(); } }
comment
This mode is more in line with the opening and closing principle, but it is very similar to the original new ProductA() and new ProductA(). The introduction of factory mode makes the design more complex.
application
JDBC
Connection conn=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/db1","db_user","123456"); Statement statement=conn.createStatement(); ResultSet rs=statement.executeQuery("select * from user");
Abstract factory pattern
To understand the abstract factory pattern, we need to understand two concepts:
- Product hierarchy structure: the product hierarchy structure is the inheritance structure of the product. For example, if an abstract class is a TV, and its subclasses include Haier TV, Hisense TV and TCL TV, a product hierarchy is formed between the abstract TV and the TV of a specific brand. The abstract TV is the parent class, and the TV of a specific brand is its subclass.
- Product family: in the abstract factory model, product family refers to a group of products produced by the same factory and located in different product hierarchy, such as Haier TV and Haier refrigerator produced by Haier Electric Appliance Factory. Haier TV is located in the TV product hierarchy and Haier refrigerator is located in the refrigerator product hierarchy.
In the factory method mode, specific factories are responsible for producing specific products, and each specific factory corresponds to a specific product. Generally, there is only one factory method or a set of overloaded factory methods in a specific factory. But sometimes we need a factory that can provide multiple product objects instead of a single product object.
Class diagram
Factory1 is responsible for creating ProductA1 and ProductB1
Factory2 is responsible for creating ProductA2 and ProductB2
The client does not need to know the specific product, but only needs to know the factory created to use the product
code implementation
AbstractProductA
public abstract class AbstractProductA { public abstract void use(); }
ProductA1
public class ProductA1 extends AbstractProductA { @Override public void use() { System.out.println("You are using ProductA1..."); } }
ProductA2
public class ProductA2 extends AbstractProductA { @Override public void use() { System.out.println("You are using ProductA2..."); } }
AbstractProductB
public abstract class AbstractProductB { public abstract void eat(); }
ProductB1
public class ProductB1 extends AbstractProductB { @Override public void eat() { System.out.println("You are eating ProductB1..."); } }
ProductB2
public class ProductB2 extends AbstractProductB { @Override public void eat() { System.out.println("You are eating ProductB2..."); } }
AbstractFactory
public abstract class AbstractFactory { public abstract AbstractProductA createProductA(); public abstract AbstractProductB createProductB(); }
Factory1
public class Factory1 extends AbstractFactory { @Override public AbstractProductA createProductA() { return new ProductA1(); } @Override public AbstractProductB createProductB() { return new ProductB1(); } }
Factory2
public class Factory2 extends AbstractFactory { @Override public AbstractProductA createProductA() { return new ProductA2(); } @Override public AbstractProductB createProductB() { return new ProductB2(); } }
Main
public class Main { public static void main(String[] args) { AbstractFactory factory; factory = new Factory1(); use(factory); factory = new Factory2(); use(factory); } public static void use(AbstractFactory factory) { AbstractProductA productA = factory.createProductA(); productA.use(); AbstractProductB productB = factory.createProductB(); productB.eat(); } }
comment
Abstract factory pattern brings many classes, the structure is relatively complex, and it is troublesome to create a new product hierarchy.
Abstract factory mode has few application scenarios in practical work. Just pay attention to it