浅谈设计模式和其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 {
    
   //使用 GetComputer方法获取电脑类型的对象
   public Computer GetComputer(string computerName)
   {
   		Computer result = null;
      	if(computerName == null)
      	{
        	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);
}

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

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


要更努力地成为一名优秀的游戏开发者!
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

就一枚小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值