preface

The singleton pattern and the constructor pattern were introduced respectively. In practice, these two patterns are highly used. Another highly used design pattern is the factory pattern. Today to understand the factory model, the factory model is a kind of founder model, and the factory model itself is divided into three kinds:

  1. Simple Factory model
  2. Factory method pattern
  3. Abstract Factory pattern

1. Simple factory model

The simple factory pattern is more of a development habit, such as providing a static method in a class that returns a specific object depending on the different parameters passed in.

Take mobile payment as an example.

Abstract payment function:

public interface IPay {
    void pay(Double money);
}
Copy the code

To implement ApplePay and HuaWeiPay:

public class ApplePay implements IPay {
    @Override
    public void pay(Double money) {
        System.out.println("Paid with ApplePay." + money + "Yuan"); }}public class HuaWeiPay implements IPay {
    @Override
    public void pay(Double money) {
        System.out.println("Paid with HuaWeiPay" + money + "Yuan"); }}Copy the code

Factory to obtain payment method:

public class PayFactory {
    public static IPay getPay(String pay) {
        switch (pay) {
            case "huawei":
                return new HuaWeiPay();
            case "apple":
                return new ApplePay();
            default:
                return newApplePay(); }}}Copy the code

The test class:

public class PayMain {
    public static void main(String[] args) {
        IPay pay = PayFactory.getPay("apple");
        pay.pay(1000d);
        pay = PayFactory.getPay("huawei");
        pay.pay(5000d); }}Copy the code

Results:

As you can see, a static method is provided in the payment factory, which returns a different payment object depending on the payment type passed in to complete the final payment operation. This is the simple factory mode. Let’s look at the factory method mode.

Second, factory method mode

In the factory method pattern, we do away with PayFactory, which creates objects all together. Instead, we provide an abstraction for creating objects, and we delegate specific creation tasks to specific factories, such as getting apple Pay objects, using ApplePayFactory, The HuaWeiPayFactory is used to obtain Huawei Pay

As an example, get the payment object above: Make the following changes:

Change PayFactory to:

public interface PayFactory {
    IPay create(a);
}
Copy the code

Create ApplePayFactory and HuaWeiPayFactory to create payment objects respectively:

public class ApplePayFactory implements PayFactory {
    @Override
    public IPay create(a) {
        return newApplePay(); }}public class HuaWeiPayFactory implements PayFactory {
    @Override
    public IPay create(a) {
        return newHuaWeiPay(); }}Copy the code

Testing:

public class MethodFactoryMain {
    public static void main(String[] args) {
        IPay pay ;
        HuaWeiPayFactory huaWeiPayFactory = new HuaWeiPayFactory();
        pay = huaWeiPayFactory.create();
        pay.pay(1000d);

        ApplePayFactory applePayFactory = new ApplePayFactory();
        pay = applePayFactory.create();
        pay.pay(5000d); }}Copy the code

Results:

It can be seen that the main difference from simple factories is that instead of putting all the creation payment methods in one factory class, a unified definition of a factory to obtain payment methods, and then build different factories by different payment Pay, such as Huawei Pay factory, Apple Pay factory.

In simple factory mode, if we want to add an Oppo payment, we need to change the PayFactory class to add a type judgment, so that if it is not conducive to the expansion and stability of the project code,

In the factory method, we only need to define a factory to get the payment object, and let different manufacturers define their own payment factories, so that even if we add an Oppo payment, we only need to create OppoPay and OppoPayFactory, without changing the top-level abstraction:

public class OppoPay implements IPay {
    @Override
    public void pay(Double money) {
        System.out.println("Paid with OppoPay" + money + "Yuan"); }}public class OppoPayFactory implements PayFactory {
    @Override
    public IPay create(a) {
        return newOppoPay(); }}public class MethodFactoryMain {
    public static void main(String[] args) {
        IPay pay;
        HuaWeiPayFactory huaWeiPayFactory = new HuaWeiPayFactory();
        pay = huaWeiPayFactory.create();
        pay.pay(1000d);

        ApplePayFactory applePayFactory = new ApplePayFactory();
        pay = applePayFactory.create();
        pay.pay(5000d);

        OppoPayFactory oppoPayFactory = new OppoPayFactory();
        pay = oppoPayFactory.create();
        pay.pay(7000d); }}Copy the code

Results:

As you can see, the factory method pattern scales well without affecting the original code.

Let’s look at the abstract factory pattern

Abstract factory model

The abstract factory pattern is roughly divided into four parts:

  1. AbstractFactory AbstractFactory, which declares a set of methods for creating objects

  2. The concrete implementation of the ConcreteFactory factory, which implements the methods declared in the abstract factory to create objects, generates a set of objects

  3. AbstractProduct AbstractProduct that declares an interface for each object in which the business methods that the object has are declared

  4. ConceteeProduct The specific product, which defines what the factory is to achieve.

Let’s take payment as an example.

We know that on different mobile platforms, there are different payment methods, such as

There are payment methods for iPhone: ApplyPay, Alipay, wechat Pay and so on

HuaWei mobile phone has payment methods: HuaWeiPay, Alipay, wechat pay and so on

There are two general categories:

  1. Mobile payment (various mobile phone Pay)
  2. Software payment (Alipay, wechat, etc.)

Create abstract products: mobile payment interface and software payment interface:

public interface IPhonePay {
    void pay(Double money);
}
public interface ISoftPay {
    void pay(Double money);
}
Copy the code

Create an abstract factory:

public interface IPayFactory {
    IPhonePay createPhonePay(a);

    ISoftPay createSoftPay(a);
}
Copy the code

Implementation of mobile payment interface by Apple and Huawei respectively:

public class ApplyPay implements IPhonePay {
    @Override
    public void pay(Double money) {
        System.out.println("IPhone uses mobile payment." + money + "Yuan"); }}public class HuaWeiPay implements IPhonePay {
    @Override
    public void pay(Double money) {
        System.out.println("Huawei phone uses mobile payment" + money + "Yuan"); }}Copy the code

Implementation of software payment interface by Apple and Huawei respectively:

public class AppleSoftPay implements ISoftPay {
    @Override
    public void pay(Double money) {
        System.out.println("IPhone paid with app (Alipay/wechat)" + money + "Yuan"); }}public class HuaWeiSoftPay implements ISoftPay {
    @Override
    public void pay(Double money) {
        System.out.println("Huawei phone paid with software (Alipay/wechat)" + money + "Yuan"); }}Copy the code

The realization of payment method by Apple mobile phone and Huawei, and the concrete realization of abstract factory:

public class ApplyPayFactory implements IPayFactory {
    @Override
    public IPhonePay createPhonePay(a) {
        return new ApplyPay();
    }

    @Override
    public ISoftPay createSoftPay(a) {
        return newAppleSoftPay(); }}public class HuaWeuPayFactory implements IPayFactory {
    @Override
    public IPhonePay createPhonePay(a) {
        return new HuaWeiPay();
    }

    @Override
    public ISoftPay createSoftPay(a) {
        return newHuaWeiSoftPay(); }}Copy the code

The test class:

public class Main {
    public static void main(String[] args) {
        IPayFactory payFactory;

        payFactory = new ApplyPayFactory();
        payFactory.createPhonePay().pay(1000d);
        payFactory.createSoftPay().pay(2000d);
        
        payFactory = new HuaWeuPayFactory();
        payFactory.createPhonePay().pay(3000d);
        payFactory.createSoftPay().pay(4000d); }}Copy the code

Results:

It can be seen that in the final use, we only need to create payment factories for apple phones and Huawei phones respectively, and then we can use various payment functions of different phones. If Oppo comes along at this time, We can create OppoPhonePay, OppoSoftPay, OppoPayFactory separately.

In fact, the comparison with the above factory method can be roughly seen:

The factory method pattern is a factory for methods

The abstract factory pattern is a factory for objects

So much for the factory model, which needs to be carefully studied at work.