Factory method mode of design mode

Posted by intergroove on Fri, 04 Mar 2022 22:05:14 +0100

The design principle is a summary of some experience guiding our code design, that is, "mental method"; Object oriented is our "weapon"; Design pattern is "move".

Based on mental skill, use weapon moves to deal with complex programming problems.

Cousin: brother, I read the news today that the EU has expanded sanctions on Russian military enterprises and departments.

Me: Yes, the situation in Russia and Ukraine is so tense that European and American countries try to weaken Russia's combat effectiveness through this means. We know that military factories export weapons and equipment

In real life, there are many factories. Those that produce weapons and equipment are called "military factories"; Those who produce chemicals are called "chemical plants"; And "chip factory" and so on.

In our software development, there is also the saying of "factory".

What is "factory"?

As the name suggests, a factory is to create products. This mode encapsulates and manages the creation of objects. Generally speaking, when you create a new object, you can directly call the factory method.

Simple factory mode

The simple factory mode is to hand over the creation and initialization of classes to a factory for execution. Users don't need to care about the creation process. They just need to tell the factory what I want.

We take the "Russian Ukrainian war" as the background and the "military factory" as an example. We define a weapon IArms interface, that is, the standard specification of the product. Because many types of weapons are needed on the battlefield, here we will give two examples, guns and tanks, that is, two different products.

public interface IArms {
    public void attack() 
}

public class Gun implements IArms {
    @Override
    public void attack() {
        System.out.println("I'm a gun");
    }
}

public class Tank implements IArms {
    @Override
    public void attack() {
        System.out.println("I'm a tank");
    }
}

Now, if we want to produce products, we need factories. The following is the code implementation of "military factory":

public class MilitaryFactory {
    public IArms make(String type) {
        if (type.equalsIgnoreCase("Gun")) {
            return new Gun();
        } else if (type.equalsIgnoreCase("Tank")) {
            return new Tank();
        }
        return null;
    }
}

This "military factory" creates different weapons according to the orders ahead.

Next, let's look at how the client uses:

public class Demo {
    public static void main(String[] arg) {
        // Contact the director of the military factory
        MilitaryFactory mf = new MilitaryFactory();
        // Now the front line needs guns. Place Gun orders
        IArms gun = mf.make("Gun");
        // The war is fierce and needs Tank support. Place an order for Tank
        IArms tank = mf.make("Tank");
        
        ... // Eliminate the process of transporting weapons to the front line 
        
        // When the front line gets the weapons, join the battle
        gun.attack();
        tank.attack();
    }
}

You can more intuitively understand the simple factory mode through the following figure.

Characteristics of simple factory model

  1. It is a concrete class, non interface, non abstract class. There is an important make() method, which uses the if or switch branch to create different weapons and return them.
  2. The make() method is usually called a static factory.

Disadvantages of simple factory model

  1. Violated [open and closed principle] of design principle . If the front line needs aircraft support now, in addition to adding an aircraft weapon class (extension), it also needs to modify the factory class method (modification).
  2. When different weapons need different additional parameters, they are not supported, resulting in inflexibility.
  3. Simple factory mode uses static factory methods, which can not be inherited and rewritten, which will make the factory role unable to form a hierarchical structure based on inheritance.

Why use factory mode?

In OO design, there is an important design principle, that is, programming for interfaces rather than implementation. Whenever we use new to instantiate an object, we use implementation programming instead of interfaces. In this way, the code is bound to specific classes, which will make the code more fragile and inelastic.

The factory method pattern defines an interface for creating objects, but the subclass (specific factory) determines which class to instantiate. Factory methods let classes defer instantiation to subclasses.

The following figure can clearly express this meaning.

Then, the structural system of weapons remains unchanged. It mainly abstracts the "military factory", which defines the production interface of weapons, but is not responsible for specific weapons production. It assigns the production tasks to different derived factories. It is not so much a derived factory as a workshop in this military factory, and each workshop is responsible for the production of one kind of weapons.

public interface IArms {
    public void attack()
}

public class Gun implements IArms {
    @Override
    void attack() {
        System.out.println("I'm a gun");
    }
}

public class Tank implements IArms {
    @Override 
    void attack() {
    	System.out.println("I'm a tank");
    }
}
// The above codes remain unchanged

// Military factory interface for producing different weapons
public interface MilitaryFactory {
    public IArms make()
}

// Workshop for producing guns
public class GunFactory implements MilitaryFactory {
    @Override 
    public IArms make() {
        return new Gun();
    }
}

// Tank workshop
public class TankFactory implements MilitaryFactory {
    @Override 
    public IArms make() {
        return new Tank();
    }
}

// In the future, a workshop for producing aircraft can be built
....

You see, the first simple factory mode is to complete all production tasks in one workshop. This model is applicable to small military factories, which only produce several weapons, and other weapons will not be added frequently in the future. Therefore, one workshop is enough.

The current factory model is applicable to large military factories, which produce many kinds of weapons and will develop new weapons in the future. Then, using one workshop is far from enough. Therefore, many workshops are needed, and each workshop is responsible for the production task of one weapon. For the new weapons developed in the future, another workshop will be built to be responsible for the production, which will not affect the previous production workshops.

You see, that's how it works [open and closed principle] of design principle To make the code elastic.

So, how can the client call it at this time?

public class Demo {
    public static void main(String[] arg) {
        // The front line contacted the director of the gun production workshop of the military factory
        MilitaryFactory gunfactory = new GunFactory();
        // The front line contacted the director of the tank production workshop of the military factory
        MilitaryFactory tankfactory = new TankFactory();
        // The production workshop supervisor orders specific production tasks
        IArms gun = gunfactory.make();
        IArms tank = tankfactory.make();
        
        ... // Omit the process of transporting weapons to the front line
           
        // Get weapons on the front line and join the fire attack
        gun.attack();
        tank.attack();
    }
}

You see, you don't have to create objects by specifying types.

Advantages of factory mode

  1. More in line with the open close principle. When adding a new weapon, you only need to add the corresponding specific weapon category and the corresponding military factory subclass (production workshop). The simple mode needs to modify the judgment logic of the factory class.
  2. Comply with the principle of single responsibility. Each specific factory class is only responsible for creating corresponding weapons. The military factory class in a simple factory has complex if or switch logic judgment.
  3. Without using the static factory method, a hierarchical structure based on inheritance can be formed. The military factory class in the simple factory mode uses the static factory method.

Disadvantages of factory mode

  1. When adding new weapons, in addition to adding new weapons, it is also necessary to provide corresponding specific factory classes (production workshops). The number of system classes will increase in pairs, which increases the complexity of the system to a certain extent; At the same time, more classes need to be compiled and run, which will bring some additional overhead to the system.
  2. Considering the scalability of the system, it is necessary to introduce an abstraction layer, which is defined in the client code, which increases the abstraction and understanding difficulty of the system. In addition, DOM, reflection and other technologies may be used in the implementation, which increases the difficulty of the implementation of the system.

Application scenarios of simple factory mode and factory mode

The above two modes have their own advantages and disadvantages. Let's take a look at their respective application scenarios.

The simple factory mode is applicable to the case where the business is simple or the specific products are rarely increased. Compared with the factory mode, using the simple factory mode is more readable.

When you need to be flexible and extensible, consider using the factory mode. For example, we need to design a framework to connect to the mail server. There are three network protocols to choose from: POP3, IMAP and HTTP. We can take these three connection methods as product classes, define an interface such as IConnectMail, and then define the operation method of mail, and use different methods to realize three specific product classes (i.e. connection mode). If the new network protocol is supported later, it can achieve perfect expansion without violating the opening and closing principle.

Abstract factory pattern

Using the above two modes, you can't fight this battle if you find that there is no ammunition after you get the weapon in front. Is it because when I placed the order, I didn't make it clear that I wanted guns and bullets, tanks and shells?

It's too troublesome. There's no time to eat during the war.

At this time, the abstract factory pattern comes in handy.

Provides an interface for creating a set of related or interdependent objects without specifying their specific classes.

So what's the difference between abstract factory pattern and factory pattern?

Abstract factory pattern is an upgraded version of factory pattern, which is used to create a set of related or interdependent objects. The difference between it and the factory method mode is that the factory method mode is aimed at a product hierarchy; The abstract factory pattern is aimed at multiple product hierarchy.

In programming, a product structure is usually expressed as an interface or abstract class, that is, all products provided by the factory method pattern are derived from the same interface or abstract class, while the products provided by the abstract factory pattern are derived from different interfaces or abstract classes.

In the abstract factory model, there is a concept of product family: the so-called product family refers to the family composed of products with related functions in different product hierarchical structures. A series of products provided by the abstract factory pattern form a product family; The series of products provided by the factory method become a hierarchical structure.

Guns and tanks belong to the same product hierarchy, while bullets and shells belong to another product hierarchy. In these two product hierarchies, guns and bullets are functionally related, and tanks and shells are functionally related. Therefore, the abstract factory should combine these two different product hierarchies. When the front line wants guns, it can get bullets at the same time.

As shown in the figure below:

// Weapon interface
public interface IArms {
    public void attack()   // Weapon attack
}

public class Gun implements IArms {
    @Override
    void attack() {
        System.out.println("I'm a gun");
    }
}

public class Tank implements IArms {
    @Override 
    void attack() {
    	System.out.println("I'm a tank");
    }
}

// Ammunition interface
public interface IAmmunition {
    public void load()  // Ammunition loading
}

public class Bullet implements IAmmunition {
    @Override
    void load() {
        System.out.println("The bullet is loaded and waiting to be fired");
    }
}

public class Cannonball implements IAmmunition {
    @Override 
    void load() {
    	System.out.println("The shell is loaded and waiting to be fired");
    }
}


// Military factory interface for producing different weapons
public interface MilitaryFactory {
    public IArms makeArm()   // Production of weapons
    public IAmmunition makeAmmunition()  // Ammunition production
}

// A workshop that produces guns and bullets
public class GunFactory implements MilitaryFactory {
    @Override 
    public IArms makeArm() {
        return new Gun();
    }
    @Override 
    public IAmmunition makeAmmunition() {
        return new Bullet();
    }
}

// A workshop for producing tanks and shells
public class TankFactory implements MilitaryFactory {
    @Override 
    public IArms makeArm() {
        return new Tank();
    }
    @Override 
    public IAmmunition makeAmmunition() {
        return new Cannonball();
    }
}

// In the future, a workshop for the production of aircraft and aviation ammunition can also be built
....

Next, let's look at how the client calls:

public class Demo {
    public static void main(String[] arg) {
        // Contact the supervisor of the workshop producing guns and ammunition in the military factory
        MilitaryFactory gunFactory = new GunFactory();
        // Contact the supervisor of the tank and shell workshop of the military factory in the front
        MilitaryFactory tankFactory = new TankFactory();
        
        // The director of the gun and ammunition workshop ordered to produce guns and bullets at full power
        IArm gun = gunFactory.makeArm();
        IAmmunition bullet = gunFactory.makeAmmunition();
        // The head of the tank and shell production workshop ordered to produce tanks and shells at full power
        IArm tank = tankFactory.makeArm();
        IAmmunition cannonball = tankFactory.makeAmmunition();
        
        ... // Omit the process of transporting weapons and ammunition to the front line
        
        // Weapons and ammunition arrive at the battlefield
        bullet.load();  // Load the bullet
        gun.attack();   // Shoot
        
        cannonball.load();  // Loaded shell
        tank.attack();      // Tank attack
    }
}

Now, can you believe there's no bullet in my gun?

Advantages of abstract factory pattern

  1. The abstract factory pattern isolates the production of concrete classes so that customers do not need to know what is created.
  2. When multiple objects in a product family are designed to work together, it can ensure that the client always uses only the objects in the same product family.
  3. It is convenient to add new factory codes without modifying the existing factory codes.

Disadvantages of abstract factory pattern

Adding a new product hierarchy will be very complex, and the abstract factory and all concrete factory classes need to be modified.

Application scenario of abstract factory pattern

When the object to be created is a series of interrelated or interdependent product families, you can use the abstract factory pattern.

This means that in an inheritance system, if there are multiple hierarchies (that is, there are multiple abstract classes) and there are certain associations or constraints between the implementation classes in each hierarchy, the abstract factory pattern can be used. If there is no association or constraint between the implementation classes in each hierarchy, it is more suitable to use multiple independent factories to create products.

summary

There is no right or wrong design pattern. The key depends on how you use it.

reference resources

https://www.cnblogs.com/yssjun/p/11102162.html

https://www.cnblogs.com/toutou/p/4899388.html#_label3

https://blog.csdn.net/qq564425/article/details/81082242

Zen of design pattern

Topics: Design Pattern