Now many platforms in the login, there will be a row of options, you can choose wechat, QQ, Weibo account login, these accounts are third-party accounts for the platform. Third-party account logins have become popular in recent years and are generally developed based on the OAuth2.0 protocol. If you are not familiar with the OAuth2.0 protocol, you can search for it and it may help you to read this article.

Now because the company wants to introduce traffic to the platform, in order to lower the registration threshold and let more people use your platform, the leader decides to connect the third-party account login function on your platform. At this stage, first access wechat, Alipay, QQ, GitHub four third-party accounts to log in. Since you know OAuth2.0 protocol, you know that this is a fixed three-step operation. The first step is to obtain Authorization Code, the second step is to obtain Access Token, and the third step is to use information interface. However, the data fields and formats returned by each platform may be different. Therefore, based on your development experience, you extracted an abstract class IdentityProvider for the third-party account login module. This class mainly has the interface described in the above three steps.

public abstract class IdentityProvider {

    // Get the Authorization Code
    abstract void authorizationCode(a);

    // Obtain the Access Token
    abstract void accessToken(a);

    // Get user information
    abstract void getUserInfo(a);
}

Copy the code

Each third-party account platform inherits IdentityProvider and implements these three interfaces according to the rules of each third-party account platform. We have taken Alipay as an example and defined an AliPayIdentityProvider class, which inherits IdentityProvider class. The AliPayIdentityProvider class code is as follows:


/** * Alipay third-party login specific implementation */
public class AliPayIdentityProvider extends IdentityProvider{

    private static final String APPID = "Your application ID.";
    private static final String APPKEY = "Your private key";

    public AliPayIdentityProvider(a) {
        System.out.println("I am alipay third party landing concrete implementation");
    }

    @Override
    abstract void getUserInfo(a){
        // Get user information
    }

    @Override
    public void authorizationCode(a) {
        // Get the authorization Code
    }

    @Override
    public void accessToken(a) {
        // Obtain the access Token}}Copy the code

All four third-party account logins are implemented in the same way. In addition, you create an IdentityFactory class, which is the only entry to create instances. A static create method is provided, which returns the corresponding third-party account platform instance based on the parameters passed in. The IdentityFactory class code looks like this:

public class IdentityFactory {
    /** * third-party login instance obtained *@paramType identifier: 1: Alipay login 2: wechat login 3: QQ login 4: Github login */
    public static IdentityProvider create(int type){
        IdentityProvider identityProvider = null;
        switch (type){
            case 1:
                identityProvider = new AliPayIdentityProvider();
                break;
            case 2:
                identityProvider = new WeChatIdentityProvider();
                break;
            case 3:
                identityProvider = new QQIdentityProvider();
                break;
            case 4:
                identityProvider = new GitHubIdentityProvider();
                break;
        }
        returnidentityProvider; }}Copy the code

For example, to log in with GitHub account, call IdentityProvider IdentityProvider = identityFactory.create (4); , obtain GitHub IdentityProvider, and after obtaining the object, you can perform specific operations for logging in to GitHub account. Commit, deploy, test, launch, complete the task perfectly.

When you use a design pattern called Simple Factory mode in the implementation of third-party account login, you’re like, Oh my God, this is design mode? Yes, that’s right, that’s the design pattern. Since you’re curious, let’s take a look at the simple factory model.

Definition of the simple factory pattern

Simple Factory Pattern: Also known as Static Factory Method Pattern, is a creation Pattern. In the simple factory mode, there is a factory class that is responsible for creating instances of other classes. These instances have a common parent class. AliPayIdentityProvider and WeChatIdentityProvider are instantiated classes in our third-party account login. They all have a common parent class, IdentityProvider. In simple factory mode, the factory class can return different instances based on the parameters passed in. In our IdentityFactory class, we provide a static create(int Type), Different instances can be returned depending on the type passed in. So this is an example of the standard simple factory pattern.

This big part up here is hard to understand, right? The simple factory pattern has three main members:

  • Abstract product: The abstract product role is the parent class of all objects created and is responsible for describing the common interfaces shared by all instances, for exampleIdentityProvider
  • Concrete product: A concrete product role is a creation target, and all created objects act as instances of a concrete class of this role, for exampleAliPayIdentityProvider
  • Factory class: Responsible for implementing the internal logic that creates all instances, for exampleIdentityFactory

Let’s look again at a UML diagram of the simple factory pattern:

The simple factory model, though simple in its name, is supposed to have some advantages. Since you’re still wondering, let’s move on to the advantages of the simple factory model.

Advantages of the simple factory pattern

  • The factory class contains the necessary judgment logic to decide when to create an instance of a product class, freeing clients from the responsibility of directly creating product objects and simply “consuming” the product; The simple factory pattern achieves this separation of responsibilities by providing specialized factory classes for creating objects.
  • The client does not need to know the class name of the created specific product class, but only needs to know the corresponding parameters of the specific product class. For some complex class names, simple factory mode can reduce the memory of users.
  • By introducing configuration files, new specific product classes can be replaced and added without modifying any client code, increasing the flexibility of the system to some extent.

After the third party account login function was launched, the users of your company’s platform increased rapidly, boss was very happy, so he arranged work for you again, this time boss asked you to add the microblog account login, to achieve the use of microblog account login to your platform, after the previous experience, this thing is too simple for you. You added a new WeiBoIdentityProvider class to the system, which is used to implement the microblog account login. The WeiBoIdentityProvider class is as follows:


/** */
public class WeiBoIdentityProvider extends IdentityProvider{

    private static final String APPID = "Your application ID.";
    private static final String APPKEY = "Your private key";

    public WeiBoIdentityProvider(a) {
        System.out.println("I am micro-blog third party landing concrete implementation");
    }

    @Override
    abstract void getUserInfo(a){
        // Get user information
    }

    @Override
    public void authorizationCode(a) {
        //
    }

    @Override
    public void accessToken(a) {}}Copy the code

Add a case 5 branch to the IdentityFactory class, which returns the twitter account login instance.

public class IdentityFactory {
    /** * Third-party login verification *@paramType Identifier: 1: Alipay login 2: wechat login 3: QQ login 4: Github login 5: Weibo account */
    public static IdentityProvider crete(int type){
        IdentityProvider identityProvider = null;
        switch (type){
            case 1:
                identityProvider = new AliPayIdentityProvider();
                break;
            case 2:
                identityProvider = new WeChatIdentityProvider();
                break;
            case 3:
                identityProvider = new QQIdentityProvider();
                break;
            case 4:
                identityProvider = new GitHubIdentityProvider();
            case 5:
                identityProvider = new WeiBoIdentityProvider();
                break;
        }
        returnidentityProvider; }}Copy the code

Deploy and test weibo account login, no problem, pack online, shut down work. After the launch, a large number of users reported that their GitHub accounts could not be logged in. Young man, came out to pick up the pot, so you have to fart pidian pidian ran back to the company to work overtime to change the bug, but painful programmer. You searched and searched, and finally found that the break statement of Case 4 was deleted by you. Therefore, when logging in using GitHub account, the instance returned by IdentityFactory is always WeiBoIdentityProvider. As a result, the login of GitHub account will fail. Inadvertently a small mistake, caused a line accident. Everything went wrong with the production. You know what happened. Although this is caused by you, it is also a disadvantage of the simple factory mode. Every time you add a third party account to log in to the platform, you need to change the factory class, which will inevitably be deleted by mistake. The simple factory model is simple, but it also has some disadvantages. Let’s take a look at the disadvantages of the simple factory model.

Disadvantages of the simple factory pattern

  • Breaking the “open-close rule” and having to modify the logic of the factory class once a new product is added makes it easy to make mistakes like the one we’ve seen above, which accidentally caused an online accident
  • The factory class centralizes the creation logic for all instances (products), and if that factory fails, the entire system suffers
  • The simple factory pattern uses a static factory approach that prevents the factory roles from forming an inheritance-based hierarchy.

After this incident, you are determined to prove yourself and regain your supervisor’s appreciation, and you are determined to restructure the third-party account login module. As the old saying goes: Get up where you fall. So you think about it, and you finally have a refactoring of the IdentityFactory class. The factory class also needs to pull out an abstract class like the provider, and then each provider has its own factory, so that it can avoid making changes to the original system module when adding. So you abstract out an IdentityProviderFactory class that defines the interface that the factory needs. The IdentityProviderFactory class looks like this:

/** * third party login abstract factory */
public abstract class IdentityProviderFactory<T> {
    // Create a specific IdentityProvider
    public abstract IdentityProvider create(a);
}
Copy the code

Each third-party account platform needs to have its own production factory, which must inherit the IdentityProviderFactory class and override the create() method to instantiate its own identityProvider implementation class in the create() method. We need to create a AliPayIdentityProviderFactory, AliPayIdentityProviderFactory code is as follows:

/** * Alipay third-party login factory class */
public class AliPayIdentityProviderFactory extends IdentityProviderFactory<AliPayIdentityProvider> {
    @Override
    public IdentityProvider create(a) {
        // Alipay login implementation example
        return newAliPayIdentityProvider(); }}Copy the code

The create() method returns an instance of AliPayIdentityProvider. Each factory returns an instance of AliPayIdentityProvider. When the client calls the AliPayIdentityProvider, it does so by calling the factory instead of passing in arguments. For example, we use alipay account to log in

// Call alipay factory
IdentityProviderFactory providerFactory  = new AliPayIdentityProviderFactory();
/ / get IdentityProvider
IdentityProvider provider = providerFactory.create();
// A list of third-party authentication operations
Copy the code

After refactoring, we definitely won’t have the same problem as last time, because now each third-party account provider has its own factory, and each product is built and run independently. Congratulations, young man. You’re just about to get a raise.

During your refactoring, you also upgraded the simple Factory Pattern, which is now not called the Simple Factory Pattern, because it is not simple anymore, and is now called the Factory Method Pattern. Now that we all use the factory method pattern, let’s take a look at the factory method pattern.

Definition of the factory method pattern

The Factory Method Pattern is also called the Factory Pattern, also called the Virtual Constructor Pattern or the Polymorphic Factory Pattern, it is also a kind of class creation Pattern. The factory method pattern differs from the simple factory pattern in that instead of centralizing the creation of instances in a single factory, the factory method pattern extracts a factory parent class that defines the common interface for creating product objects, while the factory subclass generates concrete product objects. The goal is to defer the instantiation of the product class to the factory subclass to determine which specific product class should be instantiated. Just like our IdentityProviderFactory classes and class AliPayIdentityProviderFactory.

As with the simple factory pattern, we abstract the factory method pattern, which has four members:

  • Abstract product: Define the property methods that the product has, for exampleIdentityProvider
  • Specific product: Specific product implementation, for exampleAliPayIdentityProvider
  • Abstract factory: Define the abstract method of the factory, for exampleIdentityProviderFactory
  • Specific plant: Specific manufacturing plant, for exampleAliPayIdentityProviderFactory

Take a look at a UML diagram of the factory method pattern to reinforce the old convention:

We’ve already seen the benefits of factory mode when we refactor the third-party account login module. What are the advantages of factory mode?

Advantages of the factory method pattern

  • The factory method pattern is so extensible that when you add a new product to the system, you don’t need to modify the abstract factory and the interface provided by the abstract product. Instead, you can just add a concrete factory and concrete product and embrace change, just as if we wanted to access the pin account login now, we just createDingDingIdentityProviderFactoryandDingDingIdentityProviderIt’s good
  • Good encapsulation, code structure is clear. When the caller needs a specific product object, it only needs to know the class name of the product, not the specific creation process, reducing the coupling between modules
  • Shielding the product class, how the implementation of the product class changes, the caller does not need a relationship, it only relates to the interface of the product, as long as the interface remains unchanged, the upper module in the system does not need to change. Therefore, the factory method pattern is often used for decoupling. The high-level module only needs to know the abstract class of the product, and the implementation class does not need the relationship, which conforms to Demeter’s law and dependency inversion principle.

The factory method pattern has many advantages, but it also has many disadvantages, because it is impossible to have a perfect design pattern, so let’s look at the disadvantages of the factory method pattern.

Disadvantages of the factory method pattern

  • By adding complexity to the system, we split out the factory class, adding complexity to our system
  • Increased development volume, and when using the simple factory pattern, we only want to add onecaseBranch, now you need to create the class
  • Considering the scalability of the system, it is necessary to introduce an abstraction layer, which is defined in the client code, increasing the abstractness and difficulty of understanding of the system, and DOM, reflection and other technologies may be used in the implementation, increasing the difficulty of the implementation of the system

conclusion

This paper mainly introduces the simple factory mode and factory method mode these two design modes, through the third-party account login case, from the simple factory mode, step by step to the factory method mode. If you want to know more about the factory pattern, you need to refer to a lot of examples. Spring and other open source frameworks apply a lot of design patterns, and the factory pattern is naturally necessary. No matter which design pattern we learn, we can refer to these open source frameworks, which can deepen your understanding of design patterns.

The source code

Article insufficient place, hope everybody gives directions a lot, common study, common progress

The last

Play a small advertisement, welcome to scan the code to pay attention to the wechat public number: “The technical blog of the flathead brother”, progress together.