You know what?

  • How many design patterns are there for a factory?
  • Which factory pattern does not belong to the 23 design patterns
  • What problems do the three factory patterns solve, and how do they apply to the framework

If you can answer all of these questions fluently, then 🎉 congratulations, you can just like this article and quit. If you can’t speak fluently, take a good look at this article and hope you get it

Directory as follows

  • 1- Simple factory
    • define
    • Scenario, for example,
    • Blind to write code
    • Elegant implementation
    • Framework using
  • 2- Factory method
    • Same as above
  • 3- Abstract factory
    • Same as above
  • 4 – summary

Test code address: factory mode

1- Simple factory

define

🏭 The simple factory is a creative design pattern

Although it does not belong to one of the 23 design patterns of GOF, it is not a simple factory. The factory method and abstract factory that we come into contact with later are all evolved from this. Learning simple factory is an important foundation for us to learn factory method and abstract factory well

The advantage of a simple factory is obvious. You just need to pass in the right parameters to get the object you want. The disadvantage is that you have to change the logic of the factory once you add a new product

Simple Factory: I’m fine, but I don’t deserve it!

Scenario, for example,

Simple factories are rarely used in actual production. Generally, they are used in scenarios where fewer objects are created and the application layer only cares about the objects it needs but does not care about details

For example 🌰 : when we go to the grocery store to buy latiao, there is generally a two-dimensional code of aggregation payment, we can use Alipay can also use wechat pay, so how do we get this kind of scene alipay pay object, or wechat pay object?

🦐 code blind

Let’s write an abstract payment class

public abstract class Pay {
    /** * Pay abstract interface */
    public abstract void pay(a);
}
Copy the code

Then write a alipay payment class and wechat payment class to inherit the abstract payment class

public class AiPay extends Pay{
   
    @Override
    public void pay(a) {
        System.out.println(Ali Pay); }}Copy the code
public class WeChatPay extends Pay{

    @Override
    public void pay(a) {
        System.out.println("I'm wechat Pay"); }}Copy the code

So far, we have been able to get alipay, wechat pay object, write a test class to prove our powerful

public class Test {
    public static void main(String[] args) {
        // The parent class reference points to the subclass object
        Pay pay = new AiPay();
        // Call the subclass methodpay.pay(); }} Ali payment Process finished with exit code0
Copy the code

In this way, Alipay payment can be realized, but the problem is that our test class, namely our application layer, and our concrete implementation class (Alibaba payment class, wechat payment class) have strong coupling, we need a change, this is the origin of simple factory

Elegant implementation

Let’s write a simple factory and a test class to experience the beauty of a simple factory

public class PayFactory {

    public Pay pay(String payType) {
        if (Objects.equals("1", payType)) {
            return new AiPay();
        }
        if (Objects.equals("2",payType)) {
            return new WeChatPay();
        }
        return null; }}Copy the code

The test class

public class Test {
    public static void main(String[] args) {
        PayFactory payFactory = new PayFactory();
        Pay pay = payFactory.pay("1"); pay.pay(); }} Process finished with exit code0
Copy the code

This simple factory decouples our application layer from our implementation classes

Of course, we can also use reflection to compensate for the extensibility of simple factories to add code

public class PayFactory {
    public Pay pay(Class c) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Pay pay = null;
        pay = (Pay) Class.forName(c.getName())
            .newInstance();
        returnpay; }}Copy the code

The test class

public class Test {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
        PayFactory payFactory = newPayFactory(); Pay pay = payFactory.pay(AiPay.class); pay.pay(); }}Copy the code

The advantage of this is that once we add a payment method, we don’t need to pass in a specific type, just the corresponding payment class, which means we don’t need to change our factory

Framework using

We can look at a simple application of Calendar.java in the JDK

    public static Calendar getInstance(a)
    {
        return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
    }
Copy the code

Click in and look at 1672 lines

        Calendar cal = null;

        if (aLocale.hasExtensions()) {
            String caltype = aLocale.getUnicodeLocaleType("ca");
            if(caltype ! =null) {
                switch (caltype) {
                case "buddhist":
                cal = new BuddhistCalendar(zone, aLocale);
                    break;
                case "japanese":
                    cal = new JapaneseImperialCalendar(zone, aLocale);
                    break;
                case "gregory":
                    cal = new GregorianCalendar(zone, aLocale);
                    break; }}}Copy the code

Does this look familiar? And you can draw an analogy with our implementation.

The factory method

define

The 🏭 factory method is a common design pattern that eliminates a lot of ifelse by simply defining an interface for creating an object, but letting the class that implements that interface decide which class to instantiate and defer class instantiation to subclasses

Users only need to care about the factory corresponding to the product, and do not need to care about the creation of details, and the addition of new products in line with the open closed principle, improve our system scalability. The disadvantage is that it is easy to have too many classes, increasing complexity and system understanding

Scenario, for example,

The factory approach applies to creating objects that require a lot of repetitive code, and the application layer does not care about the details of how the product is created and implemented

Also use our above to buy latiao scene example

Blind to write code

In the above scenario, we can see that

public class PayFactory {

    public Pay pay(String payType) {
        if (Objects.equals("1", payType)) {
            return new AiPay();
        }
        if (Objects.equals("2",payType)) {
            return new WeChatPay();
        }
        return null; }}Copy the code

Both the Ali payment class and wechat Payment class are produced by our superclass code, while the factory method wants to postpone the implementation to the subclass, so we transform it to decouple it

Elegant implementation

Let’s write a payment factory interface and let the interface define a specification for what types of subclasses we want to get. And of course you can use abstract classes here, if you know that there are some default implementations, so let’s just use the interface

public interface PayFactory {
    Pay getPayType(a);
}
Copy the code

We want to produce an Ali pay object, so let’s write that down

public abstract class Pay {
    public abstract void pay(a);
}
Copy the code
public class AiPay extends Pay {
    @Override
    public void pay(a) {
        System.out.println(Ali Pay); }}Copy the code

This object will be produced by the subclass. We need to write an Ali Pay subfactory class to inherit the unified payment factory class, which is only responsible for producing the corresponding payment object

public class AiPayFactory implements PayFactory {

    @Override
    public Pay getPayType(a) {
        return newAiPay(); }}Copy the code

So far, we have completed a transformation, wechat pay factory is also available. So, at this point, we have the implementation down to the subclass

public class Test {
    public static void main(String[] args)  {
        PayFactory payFactory = newWeChatPayFactory(); Pay pay = payFactory.getPayType(); pay.pay(); }}Copy the code

Framework using

Let’s search for collection.java in Idea

Focus on line 189

Iterator<E> iterator(a);
Copy the code

Search the ArrayListIf I click in,You can see it clearlyiteratorReturns an inner class

In a similar way to the little demo we wrote earlier, Collection. Java is our PayFactory, and we defer the instantiation of the concrete class to the subclass

Java Retuen The object, equivalent to our PayFactory back to the specific payment class object

Does that enlighten you? If not, just look at it again

The abstract factory

define

An abstract factory, despite its name, is not abstract at all. It provides an interface for creating a set of related or interdependent objects

A series of understanding is the same product family (the specific definition of product family will be explained in 4- summary, let us first leave an impression, can be simply understood as things under the same brand, lenovo’s host, display, tablet all belong to the same product family)

The advantage of an abstract factory is that, like any other factory, it isolates the concrete product from the application layer code and does not need to worry about the details of creation. The disadvantage is that when you want to create a new product, you need to modify the interface of the abstract factory

Scenario, for example,

The abstract factory also emphasizes that the application layer does not care about the implementation details of the product, but that it produces products of the same product family

Let’s take a new business scenario. Lenovo’s desktop computer needs a host and a display screen to be a complete desktop computer. We have a computer factory to produce Lenovo’s desktop computer, or Dell’s desktop computer, etc

Elegant implementation

Since we need to produce the display and the mainframe, we need two abstract classes or interface specifications to produce the display and the mainframe

public abstract class Computer {
  
    public abstract void produce(a);
}

Copy the code
public abstract class DisplayScreen {

    public abstract void produce(a);
}

Copy the code

Once the foundation was laid, to produce a wide variety of desktop computers, we needed a large computer factory to produce mainframes and screens

public interface DesktopComputerFactory {

    Computer getComputer(a);
    
    DisplayScreen getDisplayScreen(a);
}

Copy the code

Ok, let’s move on to lenovo consoles and displays

public class LenovoComputer extends Computer {

    @Override
    public void produce(a) {
        System.out.println("Production of Lenovo mainframe"); }}Copy the code
public class LenovoDisplayScreen extends DisplayScreen{
    @Override
    public void produce(a) {
        System.out.println("Production of Lenovo display"); }}Copy the code

Lenovo’s mainframe and display screens are already in place. Next, we only need a Lenovo desktop computer factory to inherit our unified computer factory, so that we can produce Lenovo brand desktop computers. Ollie:

public class LenovoDesktopComputerFactory implements DesktopComputerFactory {

    @Override
    public Computer getComputer(a) {
        return new LenovoComputer();
    }

    @Override
    public DisplayScreen getDisplayScreen(a) {
        return newLenovoDisplayScreen(); }}Copy the code

We can see that lenovo’s computer factories are products of the same product family, producing Lenovo’s display, producing Lenovo’s mainframe

Then the factory starts to see if it can be produced correctly

public class Test {
    public static void main(String[] args) {
        DesktopComputerFactory lenovoDesktopComputerFactory = newLenovoDesktopComputerFactory(); Computer computer = lenovoDesktopComputerFactory.getComputer(); DisplayScreen displayScreen = lenovoDesktopComputerFactory.getDisplayScreen(); computer.produce(); displayScreen.produce(); }} Production lenovo computer production Lenovo computer display Process finished with exit code0
Copy the code

Already can produce the lenovo brand desktop computer perfectly, pretend to get rich further, according to the steps continue to engage in Dell, Asus and other brands can, but also in line with our open closed principle

Framework using

We open java.sql.Connection, the interface responsible for connecting to the database in Java

We can focus on lines 104 and 138

Statement createStatement() throws SQLException;
 
PreparedStatement prepareStatement(String sql) throws SQLException;
Copy the code

Everything returned in this connection is the same product family, mysql comes in as mysql Statement, PreparedStatement, Oracle comes in as Oracle Statement, PreparedStatement

Let’s take a closer look at the Statement class. This class is also an abstract factory that returns objects from the same product family, which I won’t expand on here.

summary

Summary part, let’s first say, product level and product family is how to understand

As shown in the figure, product family refers to all products of the same brand. For example, Huawei’s mobile phone and Huawei’s tablet belong to the same product family, while Huawei’s mobile phone and Apple’s mobile phone belong to the same product class. They all belong to mobile phone

For simple factories, the main concern is any product of the same product grade. (For adding new products, mainly new products, it is necessary to modify the factory class. Consistent with the single responsibility principle. Not in line with the open-closed principle)

For the factory method, the main concern is fixed products of the same product grade. (You can add any product. When adding a product, you do not need to change the existing factory. You need to add the factory corresponding to the product. In line with the single responsibility principle, in line with the open – closed principle. But it introduces complexity)

In the case of an abstract factory, it is used to produce all the products of different product families. When adding a new product, you need to modify the factory, when adding a product family, you need to add a factory. Conforms to single responsibility principle, partially conforms to open – closed principle, reduces complexity)

The three designs have their own advantages and disadvantages, and the most suitable one can be selected only by combining the actual business scenarios


Reference:

If you think the Factory model is easy, it’s probably because you only know the tip of the iceberg

Geely “Design Mode”

I’m Skow

Give me a like and I’ll see you next time