From: Factory Model – just read this one

The factory pattern

  • Simple factory
  • The factory method
  • The abstract factory

Simple factory

Let’s take warrior, archer, mage as examples.

When we want to create objects of these three classes, we can create a new hero interface. All objects that inherit this interface should implement the attack function:

package com.cc.factory.simpleFactory;

/** * hero interface *@author cc
 * @dateThe 2021-12-16 17:34 * /
public interface Hero {
    // Heroes can attack
    void attack(a);
}
Copy the code

Then create Warrior, Shooter, and Master respectively:

package com.cc.factory.simpleFactory;

/** * soldier *@author cc
 * @dateThe 2021-12-16 "* /
public class Warrior implements Hero {
    @Override
    public void attack(a) {
        System.out.println("Warrior Attack"); }}Copy the code
package com.cc.factory.simplefactory;

/** * archer *@author cc
 * @dateCame 2021-12-16 * /
public class Shooter implements Hero {
    @Override
    public void attack(a) {
        System.out.println("Archer attack"); }}Copy the code
package com.cc.factory.simplefactory;

/** ** master *@author cc
 * @dateCame 2021-12-16 * /
public class Master implements Hero {
    @Override
    public void attack(a) {
        System.out.println("Mage Attack"); }}Copy the code

Next comes a simple hero factory called HeroSimpleFactory, which instantiates different objects based on the arguments passed in:

package com.cc.factory.simpleFactory;

import com.cc.factory.simplefactory.Hero;
import com.cc.factory.simplefactory.Master;
import com.cc.factory.simplefactory.Shooter;
import com.cc.factory.simplefactory.Warrior;

/** * Hero simple factory *@author cc
 * @dateIn the 2021-12-16 s when * /
public class HeroSimpleFactory {
    public static Hero getHero(String type) {
        Hero hero = null;
        if ("warrior".equalsIgnoreCase(type)) {
            hero = new Warrior();
        } else if ("shooter".equalsIgnoreCase(type)) {
            hero = new Shooter();
        } else if ("master".equalsIgnoreCase(type)) {
            hero = new Master();
        }
        returnhero; }}Copy the code

Call the hero’s simple factory test in the main function:

package com.cc.factory.simplefactory;

public class Main {
    public static void main(String[] args) {
        {
            Hero hero = HeroSimpleFactory.getHero("warrior");
            hero.attack();
        }
        {
            Hero hero = HeroSimpleFactory.getHero("shooter");
            hero.attack();
        }
        {
            Hero hero = HeroSimpleFactory.getHero("master"); hero.attack(); }}}Copy the code

Results:

Warrior attack Archer attack mage attackCopy the code
Simple Factory Summary

From this example, we can see that the simple factory implementation is very simple, so if the system itself is not complex, the simple factory solution can be used.

But also obvious shortcomings, such as if we designed the new heroes such as elves, dwarves, simple will modify the source code of the factory, which violates the principle of open and close (open software should be to expand, but closed for modification, its meaning is said that software should be implemented by extending change, rather than by modifying existing code to implement the change).

So to follow the on/off principle, we have the factory method pattern.

The factory method

As with the hero example above, we create a new interface, HeroFactory:

package com.cc.factory.factorymethod;

/** * hero factory *@author cc
 * @dateThe 2021-12-16 17:55 * /
public interface HeroFactory {
    // Get the hero
    void getHero(a);
}
Copy the code

Create three new hero factories that implement the HeroFactory interface:

package com.cc.factory.factorymethod;

public class WarriorFacrtory implements HeroFactory {
    @Override
    public Hero getHero(a) {
        return newWarrior(); }}Copy the code
package com.cc.factory.factorymethod;

public class ShooterFacrtory implements HeroFactory {
    @Override
    public Hero getHero(a) {
        return newShooter(); }}Copy the code
package com.cc.factory.factorymethod;

public class MasterFacrtory implements HeroFactory {
    @Override
    public Hero getHero(a) {
        return newMaster(); }}Copy the code

Test it out:

package com.cc.factory.factorymethod;

public class Main {
    public static void main(String[] args) {
        {
            HeroFactory factory = new WarriorFacrtory();
            Hero hero = factory.getHero();
            hero.attack();
        }
        {
            HeroFactory factory = new ShooterFacrtory();
            Hero hero = factory.getHero();
            hero.attack();
        }
        {
            HeroFactory factory = newMasterFacrtory(); Hero hero = factory.getHero(); hero.attack(); }}}Copy the code

Results:

Warrior attack Archer attack mage attackCopy the code

This is the use of the factory method, unlike the simple factory, when we add a new hero, we create the corresponding production factory, and let the subclass factory implement the creation of the hero, in the form of extension function, which conforms to the open and closed principle.

Advantages: The factory pattern is very extensible, with each factory responsible for only one task, which also conforms to the single responsibility principle (i.e. a class is responsible for only one thing)

Summary of factory methods

One limitation of the factory method is to create only one object. Suppose we now need to create a group of objects. For example, the hero will have weapons in addition to the attack() action. The archer’s weapons, arrows, and leather armour; Wizards are armed with wands, cloth armor,

So in the factory method, just one warrior hero, we need to create the hero, longsword, heavy armor factory class, this architecture design is not good, so we have abstract factory.

The abstract factory

AbstractFactory AbstractFactory declares a set of methods for creating objects. Let’s create a hero AbstractFactory:

package com.cc.factory.abstractfactory;

/** * Hero abstract factory *@author cc
 * @dateThe 21-12-16 23:07 * /
public abstract class HeroAbstractFactory {
    abstract Hero createHero(a);
    abstract Weapon createWeapon(a);
    abstract Equip createEquip(a);
}
Copy the code

The hero abstract factory declares three methods: create hero, create weapon, and create equipment. All factory classes that inherit the hero abstract factory implement these three methods, thus achieving the purpose of producing a set of objects.

Create weapons and equipment interface classes first:

package com.cc.factory.abstractfactory;

/** ** weapon *@author cc
 * @dateThe 21-12-16 23:07 * /
public interface Weapon {
    // Create a weapon
    void action(a);
}
Copy the code
package com.cc.factory.abstractfactory;

/** ** *@author cc
 * @dateThe 21-12-16 23:09 * /
public interface Equip {
    // Create a device
    void action(a);
}
Copy the code

Then create longsword, bow, wand, and heavy, leather, and cloth armor classes respectively:

package com.cc.factory.abstractfactory;

/** * longsword *@author cc
 * @dateThe 21-12-16 and * /
public class Sword implements Weapon {
    @Override
    public void action(a) {
        System.out.println("Create the Longsword"); }}Copy the code
package com.cc.factory.abstractfactory;

/**
 * 弓箭类
 * @author cc
 * @dateThe 21-12-16: * /
public class Bow implements Weapon {
    @Override
    public void action(a) {
        System.out.println("Create a bow and arrow"); }}Copy the code
package com.cc.factory.abstractfactory;

/** ** wand class *@author cc
 * @dateThe 21-12-16 "* /
public class Wand implements Weapon {
    @Override
    public void action(a) {
        System.out.println("Create a wand."); }}Copy the code

package com.cc.factory.abstractfactory;

/** ** heavy class *@author cc
 * @dateThe 21-12-16 hands * /
public class HeavyArmor implements Equip {
    @Override
    public void action(a) {
        System.out.println("Create heavy armor"); }}Copy the code
package com.cc.factory.abstractfactory;

/** * Light class A *@author cc
 * @dateThe 21-12-16 hands * /
public class LeatherArmor implements Equip {
    @Override
    public void action(a) {
        System.out.println("Create Light armor"); }}Copy the code
package com.cc.factory.abstractfactory;

/** ** **@author cc
 * @dateThe 21-12-16 * / met
public class ClothArmor implements Equip {
    @Override
    public void action(a) {
        System.out.println("Create cloth armor"); }}Copy the code

Now you can create a hero factory:

package com.cc.factory.abstractfactory;

/** * Warrior production factory *@author cc
 * @dateThe 21-12-16 masters * /
public class WarriorFactory extends HeroAbstractFactory {
    @Override
    Hero createHero(a) {
        return new Warrior();
    }

    @Override
    Weapon createWeapon(a) {
        return new Sword();
    }

    @Override
    Equip createEquip(a) {
        return newHeavyArmor(); }}Copy the code
package com.cc.factory.abstractfactory;

/** * Archer production factory *@author cc
 * @dateThe 21-12-16 "* /
public class ShooterFactory extends HeroAbstractFactory {
    @Override
    Hero createHero(a) {
        return new Shooter();
    }

    @Override
    Weapon createWeapon(a) {
        return new Bow();
    }

    @Override
    Equip createEquip(a) {
        return newLeatherArmor(); }}Copy the code
package com.cc.factory.abstractfactory;

/** ** Mage production factory *@author cc
 * @dateThe 21-12-16:30 * /
public class MasterFactory extends HeroAbstractFactory {
    @Override
    Hero createHero(a) {
        return new Master();
    }

    @Override
    Weapon createWeapon(a) {
        return new Wand();
    }

    @Override
    Equip createEquip(a) {
        return newClothArmor(); }}Copy the code

Test it out:

package com.cc.factory.abstractfactory;

public class Main {
    public static void main(String[] args) {
        {
            HeroAbstractFactory factory = new WarriorFactory();
            Hero hero = factory.createHero();
            Weapon weapon = factory.createWeapon();
            Equip equip = factory.createEquip();

            hero.attack();
            weapon.action();
            equip.action();
        }
        {
            HeroAbstractFactory factory = new ShooterFactory();
            Hero hero = factory.createHero();
            Weapon weapon = factory.createWeapon();
            Equip equip = factory.createEquip();

            hero.attack();
            weapon.action();
            equip.action();
        }
        {
            HeroAbstractFactory factory = newMasterFactory(); Hero hero = factory.createHero(); Weapon weapon = factory.createWeapon(); Equip equip = factory.createEquip(); hero.attack(); weapon.action(); equip.action(); }}}Copy the code

Results:

Warrior Attack Create Longsword Create Heavily Armored Archer Attack Create Bow Create Light Armored Mage Attack Create Wand Create Cloth ArmorCopy the code

In the test code, we can see that by implementing the abstract factory, we can create different heroes for different factory subclasses and instantiate a set of heroes objects such as weapons.

Advantages: Abstract factories can associate and define group objects within classes without introducing new managed objects.

Disadvantages: Group object expansion can be very troublesome, as shown in the example above, if we need to add another action to the hero to release skills, we need to change all factory methods, which again violate the open closed principle.

In fact, when there is only one component in the abstract factory, it is essentially the same as the factory method, and the specific design pattern used depends on the scenario.