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

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();
        }
    }
}


http://www.kler.cn/a/585074.html

相关文章:

  • 手写一些常见算法
  • 详解分辨率、像素值与图像大小:数字图像的三大支柱
  • cocos creator使用mesh修改图片为圆形,减少使用mask,j减少drawcall,优化性能
  • 框架_C语言_数据包解析代码框架
  • 08 | 实现版本号打印功能
  • 《C#上位机开发从门外到门内》2-6:CAN总线通信
  • DAY33 贪心算法Ⅱ
  • 系统架构的评估的系统的质量属性
  • Java学习--Redis
  • 【机器人-基础知识】欧拉角、旋转矩阵和四元数
  • SQL日期处理
  • 如何在PHP中实现OAuth2认证:安全性与可扩展性
  • 【实战ES】实战 Elasticsearch:快速上手与深度实践-6.2.2GDPR数据脱敏处理
  • Visual stdio2022 opencv cude pytroch与yolov8/可视化工具的环境搭建,不搞VIP,我也要当雷锋
  • TDE透明加密:免改造实现SQLServer数据库安全存储
  • Spring Boot集成Mybatis中如何显示日志
  • AutoGen学习笔记系列(十一)Advanced - Magentic-One
  • LeetCode27移除元素
  • 学习路之TP6 --定制workman命令
  • Java×c艹py