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.