浅谈设计模式和其Unity中的应用:二、工厂模式

目录

什么是工厂模式

工厂模式(Factory Pattern)是 最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

关于具体的概念给个链接:工厂模式概念

具体场景

比如我们现在有一个工厂生成电脑,有Dell的,ASUS的,Acer的。用户需要购买电脑,工厂需要生产电脑,但是用户购买的电脑是有三种的,比如我们用户说想要Dell的就必须给他一个Dell的电脑。那这种情况就可以用工厂模式来解决。用户给需求(需要生产的电脑的名字),工厂生产(实例化具体是什么电脑),生产完用返回值返回给调用者(电脑生产完送到用户手里)。

怎么实现工厂模式(C#实现)

步骤一

首先应该有一个电脑接口

public interface Computer {
   void Func();
}

步骤二

然后有具体的电脑,创建实现接口的实体类。

public class Dell : Computer {
 
   public override void Func()
   {
    	
   }
   
}
public class ASUS: Computer {
 
   public override void Func()
   {
      
   }
   
}
public class Acer: Computer {
 
   public override void Func()
   {
      
   }
   
}

步骤三

创建一个工厂,生成基于给定信息的实体类的对象。

public class Factory {
    
   //使用 getShape 方法获取形状类型的对象
   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;
   }
}

步骤四

使用该工厂,通过传递类型信息来获取实体类的对象。

public class FactoryPatternDemo
{
 
   public static void Main(String[] args) {
   
      Factory factory = new Factory();
 
      //获取 Dell 的对象,并调用它的 Func 方法
      Computer dell = factory.GetComputer("Dell");
 
      //调用 Dell 的 Func 方法
      dell.Func();
 
      //获取 ASUS 的对象,并调用它的 Func 方法
      Computer asus = factory.GetComputer("ASUS");
 
      //调用 ASUS 的 Func 方法
      asus.Func();
 
      //获取 Acer 的对象,并调用它的 Func 方法
      Computer acer = factory.GetComputer("Acer");
 
      //调用 Acer 的 Func 方法
      acer.Func();
   }
}

在Unity中的应用(单例模式+对象池+工厂模式)

关于单例模式可以看看我的上一篇文章:浅谈设计模式和其Unity中的应用:一、单例模式
关于对象池可以看看我的这一篇文章:Unity射击游戏发射子弹的方法和提升流畅性的小技巧

具体场景

比如有一个射击游戏,有很多枪械:手枪、步枪、散弹枪、狙击步枪、冲锋枪等等,每把武器都有自己的子弹。
我们在射击的时候可以拜托工厂来创建子弹,然后返回。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BulletFactory : Singleton<BulletFactory>, BaseFactory
{
    //步枪子弹对象池
    private Stack<BulletController> m_rifleBulletPool = new Stack<BulletController>();
    //狙击步枪子弹对象池
    private Stack<BulletController> m_sniperBulletPool = new Stack<BulletController>();
    //手枪子弹对象池
    private Stack<BulletController> m_handGunBulletPool = new Stack<BulletController>();
    //散弹枪子弹对象池
    private Stack<BulletController> m_shotGunBulletPool = new Stack<BulletController>();
    //冲锋枪子弹对象池
    private Stack<BulletController> m_sMGBulletPool = new Stack<BulletController>();

    //步枪子弹预制体
    public BulletController AssaultRifleBulletPrefab;
    //狙击步枪子弹预制体
    public BulletController SniperBulletBulletPrefab;
    //手枪子弹预制体
    public BulletController HandGunBulletPrefab;
    //散弹枪子弹预制体
    public BulletController ShotGunBulletPrefab;
    //冲锋枪子弹预制体
    public BulletController SMGBulletPrefab;
    protected override void Awake()
    {
        base.Awake();
        DontDestroyOnLoad(this);
    }
    /// <summary>
    /// 创建子弹时调用
    /// </summary>
    /// <param name="produceName">子弹名称:AssaultRifle、Sniper、Handgun、SMG、ShotGun</param>
    /// <returns>子弹</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>
    /// 创建子弹时调用
    /// </summary>
    /// <param name="produceName">子弹名称:AssaultRifle、Sniper、Handgun、SMG、ShotGun</param>
    /// <param name="position">子弹位置</param>
    /// <param name="rotation">子弹旋转</param>
    /// <returns>子弹</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>
    /// 子弹重新加入对象池调用
    /// </summary>
    /// <param name="produceName">子弹名称:AssaultRifle、Sniper、Handgun、SMG、ShotGun</param>
    /// <param name="go">子弹</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);
    }
}

调用方法

public void CreatBullet(string bulletName)
{
	Component bullet = BulletFactory.Ins.Creat(bulletName);
}

工厂模式的升级——抽象工厂模式

下一篇文章我们来进一步优化工厂模式:抽象工厂模式

上一篇:ET框架6.0Demo运行学习笔记


下一篇:Unity中读取Json字符串