2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Factory Pattern is a commonly used design pattern in object-oriented programming.Creational PatternsThe factory pattern is mainly used to create objects, but it is different from using it directly in the code.new
Unlike creating objects with keywords, it creates objects through a common interface, thus separating the object creation process from the client code. The following is a detailed introduction to the factory pattern:
The factory pattern is mainly divided into three types: simple factory pattern (static factory pattern), factory method pattern and abstract factory pattern
Simple factory pattern class diagram
Factory Method Pattern
Abstract Factory Pattern
The factory pattern is widely used in actual development, such as database connection, UI controls, file processing, logging, network communication, message queues, data structures, encryption and decryption, message push, and task scheduling. In these scenarios, the factory pattern can be used to separate the object creation process from the use process, thereby improving the flexibility and scalability of the system.
In the simple factory pattern, we define a factory class that can return instances of different types based on the parameters passed in.
Below is an example of a simple factory pattern written in Java. We will create a shape factory that can produce instances of circle, rectangle, and square. First, we define a shape interface (Shape) and several concrete classes that implement the interface (Circle, Rectangle, Square).
- // 形状接口
- interface Shape {
- void draw();
- }
-
- // 圆形类
- class Circle implements Shape {
- @Override
- public void draw() {
- System.out.println("Inside Circle::draw() method.");
- }
- }
-
- // 矩形类
- class Rectangle implements Shape {
- @Override
- public void draw() {
- System.out.println("Inside Rectangle::draw() method.");
- }
- }
-
- // 正方形类
- class Square implements Shape {
- @Override
- public void draw() {
- System.out.println("Inside Square::draw() method.");
- }
- }
Next, we define a factory class (ShapeFactory) that uses static methods to generate shape objects.
- // 形状工厂类
- class ShapeFactory {
-
- // 使用 getShape 方法获取形状类型的对象
- public static Shape getShape(String shapeType){
- if(shapeType == null){
- return null;
- }
- if(shapeType.equalsIgnoreCase("CIRCLE")){
- return new Circle();
- } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
- return new Rectangle();
- } else if(shapeType.equalsIgnoreCase("SQUARE")){
- return new Square();
- }
-
- return null;
- }
- }
Finally, we can use the factory class to get shape objects and call theirdraw
method.
- public class FactoryPatternDemo {
-
- public static void main(String[] args) {
- // 获取 Circle 的对象,并调用它的 draw 方法
- Shape shape1 = ShapeFactory.getShape("CIRCLE");
- shape1.draw();
-
- // 获取 Rectangle 的对象,并调用它的 draw 方法
- Shape shape2 = ShapeFactory.getShape("RECTANGLE");
- shape2.draw();
-
- // 获取 Square 的对象,并调用它的 draw 方法
- Shape shape3 = ShapeFactory.getShape("SQUARE");
- shape3.draw();
- }
- }
In this example,ShapeFactory
The class is responsible for creatingShape
The client code passes type information (such as a string) toShapeFactory
Static methods of a classgetShape
to get an instance of the required shape. In this way, the client is decoupled from the implementation of the concrete class, which complies with the open-closed principle, that is, the new shape class can be extended without modifying the client code. However, a major disadvantage of the simple factory pattern is that if the system needs to expand a new product family (for example, in addition to the shape, there are also colors, etc.), the factory class needs to be modified, which violates part of the open-closed principle. In this case, you can consider using the factory method pattern or the abstract factory pattern.
Let’s take shape as an example. We use engineering methods to create it.
First, define the shape interface (Product) and create three implementation classes.
- // 形状接口
- interface Shape {
- void draw();
- }
-
- // 圆形类
- class Circle implements Shape {
- @Override
- public void draw() {
- System.out.println("Inside Circle::draw() method.");
- }
- }
-
- // 矩形类
- class Rectangle implements Shape {
- @Override
- public void draw() {
- System.out.println("Inside Rectangle::draw() method.");
- }
- }
-
- // 正方形类
- class Square implements Shape {
- @Override
- public void draw() {
- System.out.println("Inside Square::draw() method.");
- }
- }
Next, define the creator interface (Creator) and the concrete creator (Concrete Creator):
- // 创建者接口
- interface ShapeFactory {
- Shape getShape(String shapeType);
- }
-
- // 具体创建者类
- class RectangleFactory implements ShapeFactory {
- @Override
- public Shape getShape(String shapeType) {
- if (shapeType == null) {
- return null;
- }
- if (shapeType.equalsIgnoreCase("RECTANGLE")) {
- return new Rectangle();
- }
- return null;
- }
- }
-
- class CircleFactory implements ShapeFactory {
- @Override
- public Shape getShape(String shapeType) {
- if (shapeType == null) {
- return null;
- }
- if (shapeType.equalsIgnoreCase("CIRCLE")) {
- return new Circle();
- }
- return null;
- }
- }
-
- class SquareFactory implements ShapeFactory {
- @Override
- public Shape getShape(String shapeType) {
- if (shapeType == null) {
- return null;
- }
- if (shapeType.equalsIgnoreCase("SQUARE")) {
- return new Square();
- }
- return null;
- }
- }
Finally, use the concrete creator class to get the shape objects and call theirdraw
method:
- public class FactoryMethodPatternDemo {
-
- public static void main(String[] args) {
- ShapeFactory shapeFactory = new CircleFactory();
-
- // 获取 Circle 的对象,并调用它的 draw 方法
- Shape shape1 = shapeFactory.getShape("CIRCLE");
- shape1.draw();
-
- // 使用 RectangleFactory 来获取 Rectangle 的对象
- shapeFactory = new RectangleFactory();
- Shape shape2 = shapeFactory.getShape("RECTANGLE");
- shape2.draw();
-
- // 使用 SquareFactory 来获取 Square 的对象
- shapeFactory = new SquareFactory();
- Shape shape3 = shapeFactory.getShape("SQUARE");
- shape3.draw();
- }
- }
In this example,We create a corresponding factory class for each shape class(Although in real applications, you would usually have a more general factory class structure, perhaps using configuration files or reflection to avoid having to write a separate factory class for each product class.) This helps demonstrate the basic principles of the Factory Method pattern,That is, let the factory subclass decide which class to instantiateHowever, for the simple case in this example, you might prefer to use the Simple Factory pattern or consider other design patterns to reduce code duplication.
This example takes mobile phones as an example, abstract products related to mobile phones (such as screens, batteries, operating systems, etc.), and creates specific product classes to implement these interfaces. Then, we can define abstract factory interfaces and specific factory classes to produce these products. The following is a simplified example showing how to use the abstract factory pattern to produce mobile phone components (screens and batteries) of different brands and models:
First, define the product interface and specific products:
- // 屏幕接口
- interface Screen {
- void display();
- }
-
-
- // 高端屏幕的实现
- class HighEndScreen implements Screen {
- @Override
- public void display() {
- System.out.println("显示高清屏幕");
- }
- }
-
- // 低端屏幕的实现
- class LowEndScreen implements Screen {
- @Override
- public void display() {
- System.out.println("显示普通屏幕");
- }
- }
-
-
- // 电池接口
- interface Battery {
- void charge();
- }
-
-
- // 高效电池的实现
- class HighEfficiencyBattery implements Battery {
- @Override
- public void charge() {
- System.out.println("快速充电");
- }
- }
-
- // 标准电池的实现
- class StandardBattery implements Battery {
- @Override
- public void charge() {
- System.out.println("标准充电");
- }
- }
Next, define the abstract factory interface and concrete factory class:
- // 手机组件工厂接口
- interface PhoneFactory {
- Screen createScreen();
- Battery createBattery();
- }
-
- // 高端手机工厂
- class HighEndPhoneFactory implements PhoneFactory {
- @Override
- public Screen createScreen() {
- return new HighEndScreen();
- }
-
- @Override
- public Battery createBattery() {
- return new HighEfficiencyBattery();
- }
- }
-
- // 低端手机工厂
- class LowEndPhoneFactory implements PhoneFactory {
- @Override
- public Screen createScreen() {
- return new LowEndScreen();
- }
-
- @Override
- public Battery createBattery() {
- return new StandardBattery();
- }
- }
Finally, the client code, which uses the abstract factory to create concrete product objects:
- public class PhoneFactoryPatternDemo {
- public static void main(String[] args) {
- // 使用高端手机工厂
- PhoneFactory highEndFactory = new HighEndPhoneFactory();
- Screen highEndScreen = highEndFactory.createScreen();
- Battery highEndBattery = highEndFactory.createBattery();
-
- highEndScreen.display();
- highEndBattery.charge();
-
- // 使用低端手机工厂
- PhoneFactory lowEndFactory = new LowEndPhoneFactory();
- Screen lowEndScreen = lowEndFactory.createScreen();
- Battery lowEndBattery = lowEndFactory.createBattery();
-
- lowEndScreen.display();
- lowEndBattery.charge();
- }
- }
In this example, we define two mobile phone factories (high-end and low-end), each capable of producing a specific type of screen and battery.The client code interacts with the specific factory class through the abstract factory interface, thereby achieving decoupling from the specific product class.In this way, if we need to add new types of mobile phones in the future (for example, mid-range mobile phones), we only need to add new product classes and corresponding factory classes without modifying existing client code.
The factory pattern is a very useful design pattern.It has the advantages of encapsulating the object creation process, reducing coupling, improving the scalability and maintainability of the program, etc., which has been widely used in software development. However, it also has someDisadvantages, such as excessive factory responsibilities and difficulty in system expansion, etc.Therefore, in practical applications, it is necessary to make trade-offs and choices based on specific scenarios and requirements.
If the factory pattern (simple factory, factory method, abstract factory) is useful to you, remember to like and collect it.