当前位置: 首页 > news >正文

unity几种设计模式(自用)

unity的几种设计模式

      • 1.单例模式
      • 2.观察者模式
      • 3.工厂模式
      • 4.状态模式
      • 5.命令模式

1.单例模式

public class GameManager : MonoBehaviour
{
    public static GameManager Instance { get; private set; }

    void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }
}

确保全局的一个类只有一个实例。非静态的方法也可以像静态函数那样使用了。

2.观察者模式

using System;
public class Kettle
{
	public delegate void BoilingHandler(string message);
    // 定义事件,基于自定义委托 BoilingHandler
    public event BoilingHandler OnBoiling;

    // 烧水方法
    public void BoilWater()
    {
        Console.WriteLine("Kettle: Water is boiling...");
        OnBoiling?.Invoke("The water is boiling!"); // 触发事件
    }
}
public class Person
{
    public string Name { get; }

    public Person(string name)
    {
        Name = name;
    }

    // 事件处理方法
    public void HandleBoiling(string message)
    {
        Console.WriteLine($"{Name} received a message: {message}");
    }
}

class Program
{
    static void Main(string[] args)
    {
        // 创建水壶对象
        Kettle kettle = new Kettle();

        // 创建观察者(人)
        Person alice = new Person("Alice");
        Person bob = new Person("Bob");

        // 订阅事件
        kettle.OnBoiling += alice.HandleBoiling;
        kettle.OnBoiling += bob.HandleBoiling;

        // 烧水
        kettle.BoilWater();

        // 取消订阅(可选)
        kettle.OnBoiling -= bob.HandleBoiling;

        // 再次烧水
        Console.WriteLine("\nBob unsubscribed. Boiling again...");
        kettle.BoilWater();
    }
}

当观察者观察的对象出现变化满足某种条件时,记录变化,所有依赖它的对象都会收到通知。
比如:角色受伤->通知UI显示
水烧开了->通知报警器和显示器
角色死亡了->通知控制器和游戏结束UI
逻辑:在被观察者类里面新建事件和事件的调用,订阅观察者类里的某些函数,达到某种要求通知所有观察者。

3.工厂模式

1. 定义产品接口
首先,我们定义一个 IShape 接口(也可以使用抽象类和抽象方法),所有具体的形状类都需要实现这个接口。
public interface IShape
{
    void Draw();
}

2. 定义新产品
public class Circle : IShape
{
    public void Draw()
    {
        Console.WriteLine("Drawing a Circle.");
    }
    public void Print();
}

public class Rectangle : IShape
{
    public void Draw()
    {
        Console.WriteLine("Drawing a Rectangle.");
    }
}
3. 工厂类
public class ShapeFactory
{
    public IShape CreateShape(string shapeType)
    {
        if (shapeType.Equals("Circle", StringComparison.OrdinalIgnoreCase))
        {//比较字符串, 忽略大小写因素
            return new Circle();
        }
        else if (shapeType.Equals("Rectangle", StringComparison.OrdinalIgnoreCase))
        {
            return new Rectangle();
        }
        else
        {
            throw new ArgumentException("Invalid shape type.");
        }
    }
}
4. 使用工厂
using System;

class Program
{
    static void Main(string[] args)
    {
        ShapeFactory shapeFactory = new ShapeFactory();

        // 创建圆形
        IShape circle = shapeFactory.CreateShape("Circle");
        circle.Draw();

        // 创建矩形
        IShape rectangle = shapeFactory.CreateShape("Rectangle");
        rectangle.Draw();

        // 尝试创建不支持的形状
        try
        {
            IShape unknownShape = shapeFactory.CreateShape("Triangle");
            unknownShape.Draw();
        }
        catch (ArgumentException ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

一般都是写一个接口里面包含各种方法,继承的子类必须完成这些函数的实现,也可以再此基础上扩展。

4.状态模式

和状态机一模一样。

5.命令模式

实现命令接口类对应几种不同的命令
using UnityEngine;
using System.Collections.Generic;

// 命令接口
public interface ICommand
{
    void Execute();
    void Undo();
}

// 具体命令类:向前移动
public class MoveForwardCommand : ICommand
{
    private Transform _transform;
    private Vector3 _previousPosition;

    public MoveForwardCommand(Transform transform)
    {
        _transform = transform;
    }

    public void Execute()
    {
        _previousPosition = _transform.position;
        //记录当前命令执行的位置
        _transform.Translate(Vector3.forward * Time.deltaTime);
    }

    public void Undo()
    {
        _transform.position = _previousPosition;
    }
}
命令调用者:
public class CommandInvoker
{
    private Stack<ICommand> _commandHistory = new Stack<ICommand>();

    public void ExecuteCommand(ICommand command)
    {
        command.Execute();
        _commandHistory.Push(command);
    }

    public void UndoLastCommand()
    {
        if (_commandHistory.Count > 0)
        {
            ICommand lastCommand = _commandHistory.Pop();
            //移除并返回栈顶
            lastCommand.Undo();
        }
    }
}
主函数:
public class CommandExample : MonoBehaviour
{
    private CommandInvoker _invoker;

    private void Start()
    {
        _invoker = new CommandInvoker();
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.W))
        {
            ICommand moveForwardCommand = new MoveForwardCommand(transform);
            _invoker.ExecuteCommand(moveForwardCommand);
        }
        else if (Input.GetKeyDown(KeyCode.S))
        {
            ICommand moveBackwardCommand = new MoveBackwardCommand(transform);
            _invoker.ExecuteCommand(moveBackwardCommand);
        }
        else if (Input.GetKeyDown(KeyCode.Z))
        {
            _invoker.UndoLastCommand();
        }
    }
}

相关文章:

  • 【复习】补充
  • Cookie与Session详解
  • C++ string
  • ES6(1) 简介与基础概念
  • 计算机二级——Python:Day1
  • 力扣215.数组中的第K个最大元素--堆排序法(java)
  • 透过安全事件看软件组成分析SCA
  • 26岁赵露思病好后大变样,穿披肩染奶奶灰意外惊艳,复工后美回巅峰
  • 专题|Python贝叶斯金融数据应用实例合集:随机波动率SV模型、逻辑回归、参数更新、绩效比较BEST分析亚马逊股票、普尔指数...
  • Linux 守护进程与 SSH 安全配置指南
  • 【草原之歌】:守护绿色的律动与《草原法》的力量
  • Practical Coding Function Design for Time-of-Flight Imaging文章解读,CVPR2019
  • 智能合约:Solidity(基于以太坊或兼容链,如 Polygon、BSC)(仅供学习区块链知识,不可进行违法开发应用)
  • 基于DeepSeek×MWORKS 2025a的ROM Builder自动化降阶实战
  • php将身份证号写入excel文件出现科学计数法问题解决
  • 详解CPU的组成与功能
  • leetcode hot100贪心
  • 使用自动导入后,eslint报错 eslint9
  • CCF CSP 第30次(2023.09)(1_坐标变换_C++)(先输入再计算;边输入边计算)
  • Xshell连接autodl时提示ssh服务器拒绝了密码,请再试一次
  • 哪家网站做旅游攻略好/精准引流怎么推广
  • 大观网站建设/百度免费下载安装
  • 如何自己做网站发布到服务器上面/福建百度代理公司
  • 红安县城乡建设局网站/免费好用的网站
  • 自适应网站怎么做m站/无锡网站seo顾问
  • 网站常规后台/百度付费推广的费用