What is the factory model
Factory Pattern is one of the most commonly used design patterns. This type of design pattern is a creation pattern, which provides the best way to create objects.
In factory mode, when creating objects, we do not expose the creation logic to the client, and point to the newly created objects by using a common interface.
Give me a link to specific concepts: Factory model concept
Specific scenario
For example, we now have a factory generated computer, including Dell, ASUS and Acer. Users need to buy computers and factories need to produce computers, but there are three kinds of computers that users buy. For example, if our users want Dell, they must give them a Dell computer. Then this situation can be solved with the factory model. The user gives the demand (the name of the computer to be produced), factory production (instantiate the specific computer), and the return value after production is returned to the caller (the computer is delivered to the user after production).
How to implement factory mode (C# Implementation)
Step 1
First, there should be a computer interface
public interface Computer { void Func(); }
Step 2
Then there is a specific computer to create an entity class that implements the interface.
public class Dell : Computer { public override void Func() { } }
public class ASUS: Computer { public override void Func() { } }
public class Acer: Computer { public override void Func() { } }
Step 3
Create a factory to generate objects of entity classes based on the given information.
public class Factory { //Use the getShape method to get an object of shape type public Computer GetComputer(string computerName) { if(computerName == null) { result = null; } Computer result = null; switch(computerName) { case: "Dell": result = new Dell(); break; case: "ASUS": result = new ASUS(); break; case: "Acer": result = new Acer(); break; default: result = null; break; } return result; } }
Step 4
Using this factory, the object of the entity class is obtained by passing type information.
public class FactoryPatternDemo { public static void Main(String[] args) { Factory factory = new Factory(); //Get the Dell object and call its Func method Computer dell = factory.GetComputer("Dell"); //Call Dell's Func method dell.Func(); //Get the object of ASUS and call its Func method Computer asus = factory.GetComputer("ASUS"); //Call Func method of ASUS asus.Func(); //Get the object of Acer and call its Func method Computer acer = factory.GetComputer("Acer"); //Call the Func method of Acer acer.Func(); } }
Application in Unity (singleton mode + object pool + factory mode)
For the singleton mode, please refer to my previous article: On design pattern and its application in Unity: I. single case pattern
See my article on object pool: Unity shooting game method of firing bullets and tips to improve fluency
Specific scenario
For example, there is a shooting game. There are many guns: pistols, rifles, shotguns, sniper rifles, submachine guns, etc. each weapon has its own bullets.
When shooting, we can ask the factory to create bullets and return.
using System.Collections; using System.Collections.Generic; using UnityEngine; public class BulletFactory : Singleton<BulletFactory>, BaseFactory { //Rifle bullet object pool private Stack<BulletController> m_rifleBulletPool = new Stack<BulletController>(); //Sniper rifle bullet object pool private Stack<BulletController> m_sniperBulletPool = new Stack<BulletController>(); //Pistol bullet object pool private Stack<BulletController> m_handGunBulletPool = new Stack<BulletController>(); //Shotgun bullet object pool private Stack<BulletController> m_shotGunBulletPool = new Stack<BulletController>(); //Submachine gun bullet object pool private Stack<BulletController> m_sMGBulletPool = new Stack<BulletController>(); //Rifle bullet preform public BulletController AssaultRifleBulletPrefab; //Sniper rifle bullet preform public BulletController SniperBulletBulletPrefab; //Pistol bullet preform public BulletController HandGunBulletPrefab; //Shotgun bullet preform public BulletController ShotGunBulletPrefab; //Submachine gun bullet preform public BulletController SMGBulletPrefab; protected override void Awake() { base.Awake(); DontDestroyOnLoad(this); } /// <summary> ///Called when a bullet is created /// </summary> ///< param name = "producename" > bullet Name: AssaultRifle, Sniper, Handgun, SMG, shotgun < / param > ///< returns > bullet < / returns > public Component Creat(string produceName) { BulletController res = null; switch (produceName) { case "AssaultRifle": if(m_rifleBulletPool.Count >= 1) { res = m_rifleBulletPool.Pop(); } else { res = Instantiate(AssaultRifleBulletPrefab); } break; case "Sniper": if (m_sniperBulletPool.Count >= 1) { res = m_sniperBulletPool.Pop(); } else { res = Instantiate(SniperBulletBulletPrefab); } break; case "Handgun": if (m_handGunBulletPool.Count >= 1) { res = m_handGunBulletPool.Pop(); } else { res = Instantiate(HandGunBulletPrefab); } break; case "SMG": if (m_sMGBulletPool.Count >= 1) { res = m_sMGBulletPool.Pop(); } else { res = Instantiate(SMGBulletPrefab); } break; case "ShotGun": if (m_shotGunBulletPool.Count >= 1) { res = m_shotGunBulletPool.Pop(); } else { res = Instantiate(ShotGunBulletPrefab); } break; default: break; } res.gameObject.SetActive(true); return res.transform; } /// <summary> ///Called when a bullet is created /// </summary> ///< param name = "producename" > bullet Name: AssaultRifle, Sniper, Handgun, SMG, shotgun < / param > ///< param name = "position" > bullet position < / param > ///< param name = "rotation" > bullet rotation < / param > ///< returns > bullet < / returns > public Component Creat(string produceName, Vector3 position, Quaternion rotation) { Component go = Creat(produceName); go.transform.position = position; go.transform.rotation = rotation; return go; } /// <summary> ///Bullet rejoin object pool call /// </summary> ///< param name = "producename" > bullet Name: AssaultRifle, Sniper, Handgun, SMG, shotgun < / param > ///< param name = "go" > bullet < / param > public void RecoveryGameObjectToPool(string produceName, Component go) { switch (produceName) { case "AssaultRifle": m_rifleBulletPool.Push(go as BulletController); break; case "Sniper": m_sniperBulletPool.Push(go as BulletController); break; case "Handgun": m_handGunBulletPool.Push(go as BulletController); break; case "SMG": m_shotGunBulletPool.Push(go as BulletController); break; case "ShotGun": m_sMGBulletPool.Push(go as BulletController); break; default: break; } go.gameObject.SetActive(false); } }
Call method
public void CreatBullet(string bulletName) { Component bullet = BulletFactory.Ins.Creat(bulletName); }
Upgrade of factory pattern -- Abstract Factory Pattern
In the next article, let's further optimize the factory pattern: abstract factory pattern