游戏设计模式

单列模式

概念

单例模式是一种创建型设计模式,可以保证一个类只有一个实例,并提供一个访问该实例的全局节点。

优点

  • 可以派生:在单例类的实例构造函数中可以设置以允许子类派生。
  • 受控访问:因为单例类封装他的唯一实例,所以它可以严格的控制其他程序怎样以及何时访问它。
  • 可以获得一个指向该实例的全局访问节点。
  • 仅在首次请求单例对象时对其进行初始化。

缺点

  • 违反了单一职责原则。
  • 单例模式一般不要支持序列化,因为这也有可能导致多个对象实例。
  • 多线程环境下需要进行特殊处理, 避免多个线程多次创建单例对象。

组成

1.单例(Singleton)类声明了一个名为get­Instance的静态方法来返回其所属类的一个相同实例。

2.单例的构造函数必须私有化,即对客户端(Client)隐藏。调用get­Instance方法必须是获取单例对象的唯一方式。

案例

方式1

public class Singleton
{private Singleton() { }private static Singleton instance;public static Singleton GetInstance{get{if (instance == null){instance = new Singleton();}return instance;}}
}

方式2:多线程单例

class SingletonThread
{private SingletonThread() { } //私有化构造private static volatile SingletonThread instance;private static object lockHelper = new Object { };public static SingletonThread GetInstance{get{// 双重校验,为避免额外的性能消耗。if (instance == null){// 当第一个线程运行到这里时,此时会对lock加锁。// 当第二个线程运行该方法时,首先检测到lock加锁状态,该线程就会挂起等待第一个线程解锁。lock (lockHelper){if (instance == null){instance = new SingletonThread();}}}return instance;}}
}

方式3

class SingletonRead
{private SingletonRead() { }//只要访问就会被执行静态构造器,不使用不会进行实例化public static readonly SingletonRead Instance = new SingletonRead();//等价于//public static readonly SingletonRead Instance;//static SingletonRead ()//{//    Instance = new SingletonRead ();//}
}

MVC模式

概念

MVC设计模式一般指MVC框架,M(Model)指数据模型层,V(View)指视图层,C(Controller)指控制层。其设计目的是将M和V的实现代码分离,使同一个程序可以有不同的表现形式。

优点

  • 多视图共享一个模型,大大提高了代码的重用性。
  • MVC三个模块相互独立,松耦合架构。
  • 控制器提高了应用程序的灵活性和可配置性。
  • 有利于软件工程化管理。

 总之,我们通过MVC设计模式最终可以打造出一个松耦合+高可重用性+高可适用性的完美架构。

缺点

  • 原理复杂。
  • 增加了系统结构和实现的复杂性。
  • 视图对模型数据的低效率访问。

MVC并不适合小型甚至中型规模的项目,花费大量时间将MVC应用到规模并不是很大的应用程序,通常得不偿失,所以对于MVC设计模式的使用要根据具体的应用场景来决定。

组成

  • 视图层(View):负责格式化数据并把它们呈现给用户,包括数据展示、用户交互、数据验证、界面设计等功能。
  • 控制层(Controller):负责接收并转发请求,对请求进行处理后,指定视图并将响应结果发送给客户端。
  • 数据模型层(Model):模型对象拥有最多的处理任务,是应用程序的主体部分,它负责数据逻辑(业务规则)的处理和实现数据操作(即在数据库中存取数据)。

案例

新建StudentView.cs、StudentModel.cs和StudentController.cs,分别作为视图层、数据模型层和控制层。

StudentView.cs

using UnityEngine;public class StudentView
{public void PrintStudentDetails(string studentName, string studentRollNo){Debug.Log("Student: ");Debug.Log("Name: " + studentName);Debug.Log("Roll No: " + studentRollNo);}
}

StudentModel.cs

public class StudentModel
{private string name;private string rollNo;public string Name { get => name; set => name = value; }public string RollNo { get => rollNo; set => rollNo = value; }
}

 StudentController.cs

public class StudentController
{private StudentModel model;private StudentView view;public StudentController(StudentModel model, StudentView view){this.model = model;this.view = view;}public void SetStudentName(string name){model.Name = name;}public string GetStudentName(){return model.Name;}public void SetStudentRollNo(string rollNo){model.RollNo = rollNo;}public string GetStudentRollNo(){return model.RollNo;}public void UpdateView(){view.PrintStudentDetails(model.Name, model.RollNo);}
}

新建MVCPatternDemo.cs,实现代码如下:

using UnityEngine;public class MVCPatternDemo : MonoBehaviour
{private void Awake(){StudentModel model = RetrieveStudentFromDatabase();StudentView view = new StudentView();//创建一个视图:把学生详细信息输出到控制台StudentController controller = new StudentController(model, view);controller.UpdateView();controller.SetStudentName("John");//更新模型数据controller.UpdateView();}private static StudentModel RetrieveStudentFromDatabase(){StudentModel student = new StudentModel();student.Name = "Robert";student.RollNo = "10";return student;}
}

输出如下:

观察者模式

概念

观察者模式(发布-订阅模式)属于行为型模式。在程序设计中,观察者模式通常由两个对象组成:观察者和被观察者。当被观察者状态发生改变时,它会通知所有的观察者对象,使他们能够及时做出响应。

优点

解除耦合,让耦合的双方都依赖于抽象,从而使得各自的变化都不会影响另一边的变化。

缺点

在应用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者、多个观察者,开发、调试等内容会比较复杂,而且在Java中消息的通知一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。

组成

  • 抽象被观察者(Subject):定义了一个接口,包含了注册观察者、删除观察者、通知观察者等方法。
  • 具体被观察者(ConcreteSubject):实现了抽象被观察者接口,维护了一个观察者列表,并在状态发生改变时通知所有注册的观察者。
  • 抽象观察者(Observer):定义了一个接口,包含了更新状态的方法。
  • 具体观察者(ConcreteObserver):实现了抽象观察者接口,存储了需要观察的被观察者对象,并在被观察者状态发生改变时进行相应的处理。

过程

1.观察者(Observer):

观察者将自己注册到被观察者中,被观察者将观察者存放在一个容器里。

2.被观察(Subject):

被观察者发生变化时,从容器中得到所有注册过的观察者,将变化通知观察者。

3.撤销观察

观察者告诉被观察者要撤销观察,被观察者从容器中将观察者去除。

观察者将自己注册到被观察者的容器中时,被观察者不应该过问观察者的具体类型,而是应该使用观察者的接口。这样的优点是:假定程序中还有别的观察者,那么只要这个观察者也是相同的接口实现即可。一个被观察者可以对应多个观察者,当被观察者发生变化的时候,他可以将消息一一通知给所有的观察者。基于接口,而不是具体的实现,这一点为程序提供了更大的灵活性。

案例

新建ISubject.cs和IObserver.cs,分别作为抽象被观察者和抽象观察者。

新建ConcreteSubject.cs和ConcreteObserver.cs,分别作为具体被观察者和具体观察者。

脚本内容如下:

ISubject.cs

/// <summary>
/// 抽象被观察者
/// </summary>
public interface ISubject
{/// <summary>/// 添加观察者/// </summary>/// <param name="observer"></param>void AddObserver(IObserver observer);/// <summary>/// 删除观察者/// </summary>/// <param name="observer"></param>void RemoveObserver(IObserver observer);/// <summary>/// 通知观察者/// </summary>/// <param name="message"></param>void NoticeObserver(string message);
}

 IObserver.cs

/// <summary>
/// 抽象观察者
/// </summary>
public interface IObserver
{/// <summary>/// 更新消息/// </summary>/// <param name="message"></param>void UpdateMessage(string message);
}

 ConcreteSubject.cs

using System.Collections.Generic;/// <summary>
/// 具体被观察者
/// </summary>
public class ConcreteSubject : ISubject
{private List<IObserver> observers = new List<IObserver>();//存储观察者的容器public void AddObserver(IObserver observer){observers.Add(observer);}public void RemoveObserver(IObserver observer){observers.Remove(observer);}public void NoticeObserver(string message){for (int i = 0; i < observers.Count; i++){observers[i].UpdateMessage(message);}}
}

ConcreteObserver.cs

using UnityEngine;/// <summary>
/// 具体观察者
/// </summary>
public class ConcreteObserver : IObserver
{private string name;//观察者的名字public ConcreteObserver(string name){this.name = name;}public void UpdateMessage(string message){Debug.Log(name + "---接到消息: " + message);}
}

新建一个MyObserver.cs,内容如下:

using UnityEngine;public class MyObserver : MonoBehaviour
{private void Awake(){ConcreteSubject concreteSubject = new ConcreteSubject();//定义一个主题ConcreteObserver concreteObserver01 = new ConcreteObserver("李先生");//实例化一个观察者ConcreteObserver concreteObserver02 = new ConcreteObserver("王女士");//实例化一个观察者//李先生和王女士订阅该主题concreteSubject.AddObserver(concreteObserver01);concreteSubject.AddObserver(concreteObserver02);concreteSubject.NoticeObserver("俄罗斯和乌克兰打起来了");//通知所有观察者(订阅者)//王女士取消订阅该主题concreteSubject.RemoveObserver(concreteObserver02);concreteSubject.NoticeObserver("国际形势逐步紧张起来");//通知所有观察者(订阅者)}
}

最终输出如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/247909.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

prism 10 for Mac v10.1.1.270激活版 医学绘图分析软件

GraphPad Prism 10 for Mac是一款专为科研工作者和数据分析师设计的绘图和数据可视化软件。以下是该软件的一些主要功能&#xff1a; 软件下载&#xff1a;prism 10 for Mac v10.1.1.270激活版 数据整理和导入&#xff1a;GraphPad Prism 10支持从多种数据源导入数据&#xff0…

Linux的bash命令语法

可用点 #!/bin/bash # 文件要以上面开始,.sh结尾的文件不需要# 赋权文件可执行权限 chmod x <fileName># 获取java jar包启动的进程id ps -ef | grep *.jar | grep -v grep | awk {print $2}shell变量 变量命令规则&#xff1a; 只能包含字母、数字、下划线&#xff1…

银行数据仓库体系实践(6)--调度系统

调度系统是数据仓库的重要组成部分&#xff0c;也是每个银行或公司一个基础软件或服务&#xff0c;需要在全行或全公司层面进行规划&#xff0c;在全行层面统一调度工具和规范&#xff0c;由于数据类系统调度作业较多&#xff0c;交易类系统批量优先级高&#xff0c;为不互相影…

uniapp对接微信APP支付返回requestPayment:fail [payment微信:-1]General errors错误-全网总结详解

一、问题描述 uniapp对接微信APP支付&#xff0c;本来是很简单的一件事&#xff0c;后端本来就是好的&#xff0c;只要填一些参数就行了&#xff0c;搞了我一晚上&#xff0c;主要卡在uniapp这边&#xff0c;拉起支付的时候&#xff0c;一直提示以下错误&#xff1a; {"er…

js数组/对象的深拷贝与浅拷贝

文章目录 一、js中的深拷贝和浅拷贝二、浅拷贝1、Object.assign()2、利用es6扩展运算符&#xff08;...&#xff09; 二、深拷贝1、JSON 序列化和反序列化2、js原生代码实现3、使用第三方库lodash等 四、总结 一、js中的深拷贝和浅拷贝 在JS中&#xff0c;深拷贝和浅拷贝是针对…

数学电路与电子工程1(MEE)—— 锁存器和触发器

1 逻辑综合 1.1 DCB/DEC转换器 下图是一个74HC42集成电路的逻辑图&#xff0c;它是一个二进制编码的十进制&#xff08;BCD to Decimal&#xff09;转换器&#xff0c;也称为DCB/DEC转换器。这种类型的IC通常用于将4位二进制数&#xff08;BCD&#xff09;转换为十进制输出。 …

PHP文件相关函数大总结

PHP中与文件相关的函数&#xff1a; 以下示例均以读取example.txt为例&#xff1a; example.txt的内容&#xff1a; this is a txt. 这是一个文件 1 .使用 file_get_contents 读取整个文件内容&#xff1a; $fileContent file_get_contents(example.txt); echo $fileContent…

Flink问题解决及性能调优-【Flink rocksDB读写state大对象导致背压问题调优】

RocksDB是Flink中用于持久化状态的默认后端&#xff0c;它提供了高性能和可靠的状态存储。然而&#xff0c;当处理大型状态并频繁读写时&#xff0c;可能会导致背压问题&#xff0c;因为RocksDB需要从磁盘读取和写入数据&#xff0c;而这可能成为瓶颈。 遇到的问题 Flink开发…

MySql8的简单使用(1.模糊查询 2.group by 分组 having过滤 3.JSON字段的实践)

MySql8的简单使用&#xff08;1.模糊查询 2.group by 分组 having过滤 3.JSON字段的实践&#xff09; 一.like模糊查询、group by 分组 having 过滤 建表语句 create table student(id int PRIMARY KEY,name char(10),age int,sex char(5)); alter table student add height…

【C/C++ 01】初级排序算法

排序算法通常是针对数组或链表进行排序&#xff0c;在C语言中&#xff0c;需要手写排序算法完成对数据的排序&#xff0c;排序规则通常为升序或降序&#xff08;本文默认为升序&#xff09;&#xff0c;在C中&#xff0c;<algorithm>头文件中已经封装了基于快排算法的 st…

记录我的历程

1、2024年1月30号更新 从2024年1月22号开始复更&#xff0c;已添加20篇文章&#xff0c; 前一阶段&#xff1a;排名1502450、原力分2、粉丝3人

PGsql 解析json及json数组

创建测试数据 drop table if exists json_test; create table json_test as select 111 as id, {"nodes":{"1692328028076":{"nodeId":"1692328028076","nodeName":"测试表1","nodeType":"DATACO…

STM32 OV7725摄像头模块识别颜色物体(1)--HSL二值化和腐蚀中心算法,并用串口输出数据

目录 前言 一、摄像头采集数据流程 二、如何将图像显示到电脑上 三、图像二值化 1、什么是RGB? 2、RGB565转RGB888 I、RGB565和RGB888的区别 II、代码 3、RGB转HSL I、什么是HSL II、转换公式 III、代码 3、输出一张摄像头二值化图片 I、原理 II、代码 四、简单的物体识别 1、…

ElasticSearch搜索引擎入门到精通

ES 是基于 Lucene 的全文检索引擎,它会对数据进行分词后保存索引,擅长管理大量的数据,相对于 MySQL 来说不擅长经常更新数据及关联查询。这篇文章就是为了进一步了解一下它,到底是如何做到这么高效的查询的。 在学习其他数据库的时候我们知道索引是一个数据库系统极其重要…

数字图像处理(实践篇)三十六 OpenCV-Python 使用ORB和BFmatcher对两个输入图像的关键点进行匹配实践

目录 一 涉及的函数 二 实践 ORB(Oriented FAST and Rotated BRIEF)是一种特征点检测和描述算法,它结合了FAST关键点检测和BRIEF描述子。ORB算法具有以下优势: ①实时性:能够在实时应用中进行快速的特征点检测和描述。 ②

[C++]使用纯opencv部署yolov8旋转框目标检测

【官方框架地址】 https://github.com/ultralytics/ultralytics 【算法介绍】 YOLOv8是一种先进的对象检测算法&#xff0c;它通过单个神经网络实现了快速的物体检测。其中&#xff0c;旋转框检测是YOLOv8的一项重要特性&#xff0c;它可以有效地检测出不同方向和角度的物体。…

git用法总结

以gitee为例&#xff0c;GitHub也可参考本文 创建远程仓库 在自己的gitee主页 创建本地仓库 在文件夹下&#xff0c;右键→git bash here git init添加gitignore vi .gitignoregitignore里的内容根据自己实际情况设置&#xff0c;这里举个例子 # #开头的是注释 # Prer…

Oracle篇—分区索引的重建和管理(第三篇,总共五篇)

☘️博主介绍☘️&#xff1a; ✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ ✌✌️擅长Oracle、MySQL、SQLserver、Linux&#xff0c;也在积极的扩展IT方向的其他知识面✌✌️ ❣️❣️❣️大佬们都喜欢静静的看文章&#xff0c;并且也会默默的点赞收藏加关注❣…

写静态页面——魅族导航_前端页面练习

0、效果&#xff1a; 1、html代码&#xff1a;&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><…

Spring Boot通过配置文件支持数据库自定义表名

直接上干货&#xff1a; 例如一个叫xxx的项目&#xff0c;yml文件里加上这段 xxxproject:db:xxxTable: xxx_dbname #自定义的数据库表名创一个Configuration类放表名和Mapper // XxxProjectAutoConfiguration.javaConfiguration MapperScan(basePackages "cn.com.xxxp…