23 Design Patterns - Factory Pattern

Factory pattern (commonly used)

  • Factory mode introduction:
    • It provides an optimal way to create objects, we do not expose the creation logic to the client when creating objects, and use a common interface to point to newly created objects.
  • Example:
    • The factory produces computers. In addition to brand A, it can also produce computers of brands B, C, and D;
    • In business development, payment is very common, and there is a unified order and payment interface. The specific payment implementation can be WeChat, Alipay, bank card, etc.;
  • There are 3 different implementations of the factory mode :
    • Simple factory mode : return the corresponding class by passing in related types, this method is relatively simple, and the scalability is relatively poor;
    • Factory method mode : by implementing the corresponding method of the implementation class to determine the corresponding return result, this method has strong scalability;
    • Abstract factory mode : based on the expansion of the above two modes, and supports refined products;
  • Application scenario:
    • Decoupling : Separating responsibilities, separating the process of creating and using complex objects
    • Reuse code to reduce maintenance costs:
      • If the object creation is complicated and needs to be used in many places, if it is written in each place, there will be a lot of repeated code, and if the business logic changes, it needs to be modified everywhere;
      • If you use the factory mode to create uniformly, you only need to modify the factory class to reduce costs;

Factory pattern - simple factory pattern (most used)

  • Simple factory mode (static factory)

    • Also known as the static factory method, it can return instances of different classes according to different parameters, and a class is specially defined to be responsible for creating instances of other classes. The created instances usually have a common parent class;
    • Since the factory method is a static method, it can be called directly through the class name, and only simple parameters need to be passed in;
  • core composition

    • Factory : factory class, the core of the simple factory pattern, which is responsible for implementing the internal logic of creating all instances
    • IProduct : abstract product class, the parent class of all objects created by the simple factory pattern, describing the common interface shared by all instances
    • Product : Specific product category, which is the creation target of the simple factory mode
  • Implementation steps

    • Create an abstract product class , which contains the abstract method of the product, which is implemented by the specific product class
    • Create concrete product classes , inherit their parent classes, and implement concrete methods
    • Create a factory class that provides a static method createXXX()to produce products, just pass in the name of the product you want
  • advantage:

    • Separating the creation of objects from the business processing of the objects themselves can reduce the coupling of the system, making both relatively easy to modify.
  • shortcoming:

    • The responsibility of the factory class is relatively heavy. Adding new products requires modifying the judgment logic of the factory class, which is contrary to the principle of opening and closing
    • That is, the Open Close Principle is open to expansion and closed to modification. When the program needs to be expanded, the original code cannot be modified to achieve a hot- swappable effect
    • It will increase the number of classes in the system, which increases the complexity and difficulty of understanding the system to a certain extent, which is not conducive to the expansion and maintenance of the system, and the creation of simple objects does not use patterns

Let's briefly use the simple (static) factory design pattern:

Function description:

Let's simply use pseudocode to simulate the payment process:

Create an IProduct abstract product interface - IPay


/**
 * @Auther: whl
 * @Date: 2022/8/08/10:00
 * @Description: IPay抽象统一支付下单接口
 */
public interface IPay {
    
    

    /**
     * 统一下单
     */
    void unifiedOrder();
}

Create a specific implementation class for Alipay payment – ​​AliPay

/**
 * @Auther: whl
 * @Date: 2022/8/08/10:00
 * @Description: 支付宝支付具体实现类
 */
public class AliPay implements IPay{
    
    
    @Override
    public void unifiedOrder() {
    
    
        System.out.println("支付宝支付统一下单...");
    }
}

Create a specific implementation class for WeChat payment – ​​WeChatPay


/**
 * @Auther: whl
 * @Date: 2022/8/08/10:00
 * @Description: 微信支付具体实现类
 */
public class WeChatPay implements IPay{
    
    
    @Override
    public void unifiedOrder() {
    
    
        System.out.println("微信支付统一下单...");
    }
}

Create a simple payment factory class (static factory class) – SimplePayFactory


/**
 * @Auther: whl
 * @Date: 2022/8/08/10:00
 * @Description: 简单支付工厂类(静态工厂类)
 */
public class SimplePayFactory {
    
    

    /**
     * 工厂创建方法:
     * 根据参数返回对应的支付对象
     *
     * @param payType
     * @return
     */
    public static IPay createPay(String payType) {
    
    
        if (payType == null) {
    
    
            return null;
        } else if (payType.equalsIgnoreCase("WECHAT_PAY")) {
    
    
            return new WeChatPay();
        } else if (payType.equalsIgnoreCase("ALI_PAY")) {
    
    
            return new AliPay();
        }
        // 如果需要扩展,可以编写更剁
        return null;
    }
}

Test using simple payment factory:

package com.iswhl.EasyFactory;

/**
 * @Auther: whl
 * @Date: 2022/8/08/10:00
 * @Description: 简单支付工厂类(静态工厂类)
 */
public class SimplePayFactory {
    
    

    /**
     * 工厂创建方法:
     * 根据参数返回对应的支付对象
     *
     * @param payType
     * @return
     */
    public static IPay createPay(String payType) {
    
    
        if (payType == null) {
    
    
            return null;
        } else if (payType.equalsIgnoreCase("WECHAT_PAY")) {
    
    
            return new WeChatPay();
        } else if (payType.equalsIgnoreCase("ALI_PAY")) {
    
    
            return new AliPay();
        }
        // 如果需要扩展,可以编写更剁
        return null;
    }
}

The above is the factory design pattern - simple project (a simple use example of a static factory), then let's analyze its shortcomings and shortcomings:

Requirements :

  • If I need to add an additional bank card payment of Bank A, then I need to SimplePayFactoryadd the response judgment logic in the class, such as adding another ifjudgment, adding a bank A payment logic
  • And if you need another bank card payment of Bank B, then you need to add another iflogic to judge and add a bank B payment, and add it in turn...
  • Then this violates the Open Close Principle (Open Close Principle) to be followed by the factory class (open for extension, closed for modification, when the program needs to be expanded, the original code cannot be modified to achieve a hot-swappable The effect), which leads to the need to add new logic every time the function is extended, and the factory class needs to be modified. If it is a real and complex business, this will increase the cost.

Let's take a look at how the factory method pattern solves this shortcoming of the simple factory pattern

Factory Pattern - Factory Method Pattern

  • Factory Method Pattern

    • Also known as the factory mode, it is a further abstraction of the simple factory mode. Its advantage is that the system can introduce new products without modifying the original code, that is, it meets the principle of opening and closing

    • The public interface responsible for creating the product is defined through the factory class, and the type to be created is determined through the subclass

    • Compared with the simple factory, this method has more scalability and reusability , and also enhances the readability of the code

    • Delay the instantiation of the class (creation of specific products) to the subclass of the factory class (concrete factory), that is, the subclass decides which class should be instantiated

  • core composition

    • IProduct : abstract product interface, describing the common interface shared by all instances
    • Product : Concrete product class, implement the interface of abstract product class, and create objects in the factory class. If there are more than one, you need to define more than one
    • IFactory : Abstract factory interface, describing the public interface of a specific factory
    • Factory : Concrete factory class, realize the creation of product class objects, and realize the interface of abstract factory class. If there are more than one, you need to define more than one

insert image description here

IPayTo implement the factory method pattern, we only need to make improvements on the basis of the original simple factory pattern, while the abstract product interface and AliPay WeChatPaytwo concrete product classes we created before do not need to be changed.

First create IPayFactorythe abstract factory interface:

/**
 * @Auther: whl
 * @Date: 2022/8/08/10:00
 * @Description: 抽象⼯⼚接口
 */
public interface IPayFactory {
    
    
    IPay getPay();
}

Then create AliPayFactoryand WeChatFactorytwo concrete factory classes:

/**
 * @Auther: whl
 * @Date: 2022/8/08/10:00
 * @Description: 具体工厂类 AliPayFactory
 */
public class AliPayFactory implements IPayFactory{
    
    
    @Override
    public IPay getPay() {
    
    
        return new AliPay();
    }
}

/**
 * @Auther: whl
 * @Date: 2022/8/08/10:00
 * @Description: 具体工厂类 WeChatFactory
 */
public class WeChatFactory implements IPayFactory{
    
    
    @Override
    public IPay getPay() {
    
    
        return new WeChatPay();
    }
}

carry out testing:

@Test
public void testMethodPayFactory(){
    
    
    AliPayFactory aliPayFactory = new AliPayFactory();
    IPay ali_pay = aliPayFactory.getPay();
    ali_pay.unifiedOrder();// 输出:支付宝支付统一下单...
    WeChatFactory weChatFactory = new WeChatFactory();
    IPay wechat_pay = weChatFactory.getPay();
    wechat_pay.unifiedOrder();// 输出:微信支付统一下单...
}
  • Advantages of factory method pattern :

    • In line with the principle of opening and closing , adding a product category only needs to implement other specific product categories and specific factory categories;

    • In line with the principle of single responsibility , each factory is only responsible for the production of corresponding products;

    • Users only need to know the abstract class of the product, and do not need to care about other implementation classes, satisfying Dimiter's Law, Dependency Inversion Principle and Lime Replacement Principle;

      • Dimiter's law: the principle of least knowledge, entities should interact with other entities as little as possible;
      • Dependency Inversion Principle: For interface programming, rely on abstraction rather than concrete;
      • Liao replacement principle: commonly known as LSP, where any base class can appear, subclasses must appear, and the specification of the specific steps to achieve abstraction;
  • Disadvantages of factory method pattern :

    • To add a product, you need to implement the corresponding specific factory category and specific product category;
    • Each product needs to have a corresponding specific factory and specific product category;

Factory Pattern - Abstract Factory Method Pattern

The abstract factory method pattern is an integrated and upgraded version of the simple factory pattern and the factory method pattern .

  • There are 3 different implementations of the factory pattern:

    • Simple factory mode: return the corresponding class by passing in related types, this method is relatively simple, and the scalability is relatively poor;

    • Factory method mode: by implementing the corresponding method of the implementation class to determine the corresponding return result, this method has strong scalability;

    • Abstract factory mode: Based on the expansion of the above two modes, it is an upgraded version of the factory method mode. When the product to be created has multiple product lines, it is a better choice to use the abstract factory mode

    • The abstract factory pattern is the most widely used design pattern in Spring

  • background:

    • The factory method mode introduces the factory hierarchy structure, which solves the problem of heavy responsibility of the factory class in the simple factory mode
    • However, in the factory method pattern, each factory only creates objects of one type of concrete class, and subsequent development may lead to too many factory classes . Therefore, some related concrete classes are combined into a " concrete class family " by A factory for unified production emphasizes a series of related product objects ! ! !
  • Implementation steps:

    • 1. Define two interfaces IPay (payment) and IRefund (refund)
    • 2. Create specific Pay products and specific Refund products
    • 3. Create an abstract factory IOrderFactory interface with two methods createPay/createRefund
    • 4. Create the Alipay product family AliOderFactory and implement the OrderFactory abstract factory
    • 5. Create WechatOderFactory, a WeChat payment product family, and realize the abstract factory of OrderFactory
    • 6. Define a super factory creator FactoryProducer, and get the corresponding factory by passing parameters
      insert image description here

Next, we will follow the steps to use the abstract factory method pattern:

1. Define two interfaces IPay (payment) and IRefund (refund):

package com.iswhl.FactoryMethod;

/**
 * @Auther: whl
 * @Date: 2022/8/08/10:00
 * @Description: IPay抽象统一支付下单接口
 */
public interface IPay {
    
    

    /**
     * 统一下单
     */
    void unifiedOrder();
}
package com.iswhl.FactoryMethod;

/**
 * @Auther: whl
 * @Date: 2022/8/08/10:00
 * @Description: 退款抽象接口
 */
public interface IReFund {
    
    

    /**
     * 退款
     */
    void refund();
}

2. Create specific Pay products and specific Refund products:

AliPay/WeChatPay : Alipay payment and WeChat payment

package com.iswhl.FactoryMethod;

/**
 * @Auther: whl
 * @Date: 2022/8/08/10:00
 * @Description: 具体工厂类 AliPayFactory
 */
public class AliPayFactory implements IPayFactory{
    
    
    @Override
    public IPay getPay() {
    
    
        return new AliPay();
    }
}

package com.iswhl.FactoryMethod;

/**
 * @Auther: whl
 * @Date: 2022/8/08/10:00
 * @Description: 微信支付具体实现类
 */
public class WeChatPay implements IPay {
    
    
    @Override
    public void unifiedOrder() {
    
    
        System.out.println("微信支付统一下单...");
    }
}

AliRefund/WeChatFund : Alipay refund and WeChat refund

package com.iswhl.FactoryMethod;

/**
 * @Auther: whl
 * @Date: 2022/8/08/10:00
 * @Description:
 */
public class AliRefund implements IReFund {
    
    
    @Override
    public void refund() {
    
    
        System.out.println("支付宝退款...");
    }
}

package com.iswhl.FactoryMethod;

/**
 * @Auther: whl
 * @Date: 2022/8/08/10:00
 * @Description:
 */
public class WeChatRefund implements IReFund {
    
    
    @Override
    public void refund() {
    
    
        System.out.println("微信支付退款...");
    }
}

3. Create an abstract factory IOrderFactory interface with two methods createPay/createRefund:

package com.iswhl.FactoryMethod;

/**
 * @Auther: whl
 * @Date: 2022/8/08/10:00
 * @Description: 订单抽象工厂,一个超级工厂可以创建其他工厂(又被称为其他工厂的工厂)
 */
public interface IOrderFactory {
    
    

    IPay createPay();

    IReFund createRefund();
}

4. Create the Alipay product family AliOderFactory and implement the OrderFactory abstract factory:

package com.iswhl.FactoryMethod;

/**
 * @Auther: whl
 * @Date: 2022/8/08/10:00
 * @Description:
 */
public class AliOrderFactory implements IOrderFactory {
    
    
    @Override
    public IPay createPay() {
    
    
        return new AliPay();
    }

    @Override
    public IReFund createRefund() {
    
    
        return new AliRefund();
    }
}

5. Create WechatOderFactory, a WeChat payment product family, and realize the abstract factory of OrderFactory

package com.iswhl.FactoryMethod;

/**
 * @Auther: whl
 * @Date: 2022/8/08/10:00
 * @Description:
 */
public class WeChatOrderFactory implements IOrderFactory {
    
    
    @Override
    public IPay createPay() {
    
    
        return new WeChatPay();
    }

    @Override
    public IReFund createRefund() {
    
    
        return new WeChatRefund();
    }
}

6. Define a super factory creator FactoryProducer, and get the corresponding factory by passing parameters

package com.iswhl.FactoryMethod;

/**
 * @Auther: whl
 * @Date: 2022/8/08/10:00
 * @Description: 工厂创造器
 */
public class FactoryProducer {
    
    

    public static IOrderFactory getFactory(String type){
    
    
        if (type.equalsIgnoreCase("WECHAT")){
    
    
            return new WeChatOrderFactory();
        }else if (type.equalsIgnoreCase("ALI")){
    
    
            return new AliOrderFactory();
        }
        return null;
    }
}

Finally, let's test:

package com.iswhl.FactoryMethod;

public class test {
    
    
    public static void main(String[] args) {
    
    
        IOrderFactory wechatPayFactory = FactoryProducer.getFactory("WECHAT");
        wechatPayFactory.createPay().unifiedOrder();
        wechatPayFactory.createRefund().refund();
        IOrderFactory aliPayFactory = FactoryProducer.getFactory("ALI");
        aliPayFactory.createPay().unifiedOrder();
        aliPayFactory.createRefund().refund();
    }
}

The result is as follows:

微信支付统一下单...
微信支付退款...
支付宝支付 统一下单接口...
支付宝退款...
  • Factory Method Pattern and Abstract Factory Method Pattern

    • When each concrete factory class in the abstract factory pattern only creates one product object, the abstract factory pattern degenerates into a factory method pattern
  • advantage

    • When multiple objects in a product family are designed to work together, it guarantees that consumers always use only objects from the same product family
    • The product level structure is easy to expand. If you need to add another product level, you only need to add new factory categories and product categories, such as adding bank payments and refunds
  • shortcoming

    • It is difficult to expand the product family. To add a certain product in a series, it is necessary to modify the code in the abstract factory and abstract product, which does not conform to the principle of opening and closing.
    • Increased abstraction and difficulty of understanding the system

Guess you like

Origin blog.csdn.net/Ghoul___/article/details/126224996