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

C#面试常考随笔12:游戏开发中常用的设计模式【C#面试题(中级篇)补充】

C#面试题(中级篇),详细讲解,帮助你深刻理解,拒绝背话术!-CSDN博客

简单工厂模式

优点:

根据条件有工厂类直接创建具体的产品

客户端无需知道具体的对象名字,可以通过配置文件创建,灵活。

缺点:

每增加一个对象,就需要在工厂添加新的产品,修改工厂逻辑,不易拓展


 

using System;// 定义产品的抽象基类
public abstract class Product
{public abstract void Use();
}// 具体产品类A
public class ConcreteProductA : Product
{public override void Use(){Console.WriteLine("Using ConcreteProductA");}
}// 具体产品类B
public class ConcreteProductB : Product
{public override void Use(){Console.WriteLine("Using ConcreteProductB");}
}// 简单工厂类
public class SimpleFactory
{public static Product CreateProduct(string type){switch (type){case "A":return new ConcreteProductA();case "B":return new ConcreteProductB();default:throw new ArgumentException("Invalid product type");}}
}class Program
{static void Main(){Product productA = SimpleFactory.CreateProduct("A");productA.Use();Product productB = SimpleFactory.CreateProduct("B");productB.Use();}
}

工厂方法模式

解决了简单工厂的 开放-关闭原则

不同的子类由工厂子类创建

但是对象数量会很多

抽象工厂

抽象工厂:(相当于有多个工厂)不同厂商生产的同一产品,产品拥有相同的结构,区别在于不同的厂商和动作的细节。比如多个电脑工厂,生产不同品牌的电脑,电脑有多个配件,每个工厂都生产这些配件()。

抽象工厂有产品,继承的工厂生产对应厂商的产品。


using System;// 定义产品A的抽象基类
public abstract class AbstractProductA
{public abstract void UseA();
}// 具体产品A1
public class ConcreteProductA1 : AbstractProductA
{public override void UseA(){Console.WriteLine("Using ConcreteProductA1");}
}// 具体产品A2
public class ConcreteProductA2 : AbstractProductA
{public override void UseA(){Console.WriteLine("Using ConcreteProductA2");}
}// 定义产品B的抽象基类
public abstract class AbstractProductB
{public abstract void UseB();
}// 具体产品B1
public class ConcreteProductB1 : AbstractProductB
{public override void UseB(){Console.WriteLine("Using ConcreteProductB1");}
}// 具体产品B2
public class ConcreteProductB2 : AbstractProductB
{public override void UseB(){Console.WriteLine("Using ConcreteProductB2");}
}// 抽象工厂类
public abstract class AbstractFactory
{public abstract AbstractProductA CreateProductA();public abstract AbstractProductB CreateProductB();
}// 具体工厂类1,负责创建产品A1和产品B1
public class ConcreteFactory1 : AbstractFactory
{public override AbstractProductA CreateProductA(){return new ConcreteProductA1();}public override AbstractProductB CreateProductB(){return new ConcreteProductB1();}
}// 具体工厂类2,负责创建产品A2和产品B2
public class ConcreteFactory2 : AbstractFactory
{public override AbstractProductA CreateProductA(){return new ConcreteProductA2();}public override AbstractProductB CreateProductB(){return new ConcreteProductB2();}
}class Program
{static void Main(){AbstractFactory factory1 = new ConcreteFactory1();AbstractProductA productA1 = factory1.CreateProductA();AbstractProductB productB1 = factory1.CreateProductB();productA1.UseA();productB1.UseB();AbstractFactory factory2 = new ConcreteFactory2();AbstractProductA productA2 = factory2.CreateProductA();AbstractProductB productB2 = factory2.CreateProductB();productA2.UseA();productB2.UseB();}
}

观察者模式(发布-订阅)

和事件系统的逻辑基本一致

一个发布者,多个订阅者。把观察者注册进去。下图是简易的事件系统

using System;
using System.Collections.Generic;// 定义观察者接口
public interface IObserver
{void Update(string message);
}// 定义主题接口
public interface ISubject
{void RegisterObserver(IObserver observer);void RemoveObserver(IObserver observer);void NotifyObservers();
}// 具体主题类
public class ConcreteSubject : ISubject
{private List<IObserver> observers = new List<IObserver>();private string message;public void RegisterObserver(IObserver observer){observers.Add(observer);}public void RemoveObserver(IObserver observer){observers.Remove(observer);}public void NotifyObservers(){foreach (var observer in observers){observer.Update(message);}}public void SetMessage(string newMessage){message = newMessage;NotifyObservers();}
}// 具体观察者类
public class ConcreteObserver : IObserver
{private string name;public ConcreteObserver(string name){this.name = name;}public void Update(string message){Console.WriteLine($"{name} received message: {message}");}
}class Program
{static void Main(){// 创建主题ConcreteSubject subject = new ConcreteSubject();// 创建观察者ConcreteObserver observer1 = new ConcreteObserver("Observer 1");ConcreteObserver observer2 = new ConcreteObserver("Observer 2");// 注册观察者subject.RegisterObserver(observer1);subject.RegisterObserver(observer2);// 主题发布消息subject.SetMessage("New message from the subject!");// 移除一个观察者subject.RemoveObserver(observer2);// 主题再次发布消息subject.SetMessage("Another message from the subject!");}
}

状态模式

特点:

和FSM有限状态机是相似逻辑,可以说FSM是状态模式的运用

将状态相关的行为封装到不同的状态类中,使得状态的变化和对象行为的变化能够独立进行,符合开闭原则。

游戏中角色的不同状态(如奔跑、跳跃、攻击等)可用状态模式实现,每个状态有不同行为逻辑

using System;// 定义状态接口
public interface IState
{void Handle(Context context);
}// 具体状态类A
public class ConcreteStateA : IState
{public void Handle(Context context){Console.WriteLine("Handling state A. Transitioning to state B.");context.State = new ConcreteStateB();}
}// 具体状态类B
public class ConcreteStateB : IState
{public void Handle(Context context){Console.WriteLine("Handling state B. Transitioning to state A.");context.State = new ConcreteStateA();}
}// 上下文类
public class Context
{private IState state;public Context(IState initialState){this.state = initialState;}public IState State{get { return state; }set{state = value;Console.WriteLine($"State changed to {state.GetType().Name}");}}public void Request(){state.Handle(this);}
}class Program
{static void Main(){// 创建初始状态IState initialState = new ConcreteStateA();// 创建上下文对象Context context = new Context(initialState);// 执行请求,触发状态转换context.Request();context.Request();}
}
  1. IState 接口:定义了状态的行为方法 Handle,具体的状态类需要实现该方法。
  2. ConcreteStateA 和 ConcreteStateB 类:实现了 IState 接口,分别代表不同的状态,在 Handle 方法中处理当前状态的逻辑,并可以进行状态的转换。
  3. Context 类:维护一个当前状态的引用 state,通过 Request 方法调用当前状态的 Handle 方法,同时提供了 State 属性用于改变当前状态。

优点

  • 可维护性高:将不同状态的行为封装到不同的状态类中,使得代码结构清晰,易于理解和维护。当需要添加新的状态时,只需要创建一个新的状态类并实现相应的行为,而不需要修改现有的代码。
  • 可扩展性强:符合开闭原则,对扩展开放,对修改关闭。可以方便地添加新的状态和状态转换逻辑,而不会影响其他状态类和上下文类。
  • 状态转换清晰:状态的转换逻辑集中在状态类中,使得状态转换的规则更加清晰,易于管理和调试。

缺点

  • 类的数量增加:每个状态都需要一个对应的状态类,当状态较多时,会导致类的数量增加,增加了系统的复杂性。
  • 状态之间的耦合:状态类之间可能存在一定的耦合,特别是在状态转换时,一个状态类可能需要知道其他状态类的信息,这可能会影响代码的可维护性。

 装饰器模式

动态地给对象添加额外职责。游戏中给角色添加装备或增益效果可使用装饰器模式

 

using System;// 定义组件接口
public interface IComponent
{void Operation();
}// 具体组件类
public class ConcreteComponent : IComponent
{public void Operation(){Console.WriteLine("ConcreteComponent: Performing basic operation.");}
}// 装饰器抽象类
public abstract class Decorator : IComponent
{protected IComponent component;public Decorator(IComponent component){this.component = component;}public virtual void Operation(){if (component != null){component.Operation();}}
}// 具体装饰器类A
public class ConcreteDecoratorA : Decorator
{public ConcreteDecoratorA(IComponent component) : base(component){}public override void Operation(){base.Operation();AddedBehaviorA();}private void AddedBehaviorA(){Console.WriteLine("ConcreteDecoratorA: Adding additional behavior A.");}
}// 具体装饰器类B
public class ConcreteDecoratorB : Decorator
{public ConcreteDecoratorB(IComponent component) : base(component){}public override void Operation(){base.Operation();AddedBehaviorB();}private void AddedBehaviorB(){Console.WriteLine("ConcreteDecoratorB: Adding additional behavior B.");}
}class Program
{static void Main(){// 创建具体组件IComponent component = new ConcreteComponent();// 使用具体装饰器A包装组件IComponent decoratedComponentA = new ConcreteDecoratorA(component);// 使用具体装饰器B包装经过装饰器A包装的组件IComponent decoratedComponentB = new ConcreteDecoratorB(decoratedComponentA);// 调用操作方法decoratedComponentB.Operation();}
}

优点:

  • 装饰类和被装饰类可以独立发展,不会相互耦合。

  • 装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。

缺点:

  • 多层装饰比较复杂。

适配器模式

将一个类的接口转换成客户希望的另一个接口。适配器模式主要有类适配器模式和对象适配器模式两种实现方式。

对象适配器:相当于把对象作为一个属性

类适配器:相当于继承

对象:

using System;// 目标接口,客户端所期望的接口
public interface ITarget
{void Request();
}// 适配者类,需要被适配的类
public class Adaptee
{public void SpecificRequest(){Console.WriteLine("Adaptee: Specific request.");}
}// 适配器类,实现目标接口并持有适配者对象
public class Adapter : ITarget
{private Adaptee adaptee;public Adapter(Adaptee adaptee){this.adaptee = adaptee;}public void Request(){adaptee.SpecificRequest();}
}class Program
{static void Main(){// 创建适配者对象Adaptee adaptee = new Adaptee();// 创建适配器对象并传入适配者对象ITarget adapter = new Adapter(adaptee);// 通过适配器调用目标接口方法adapter.Request();}
}

类:

using System;// 目标接口
public interface ITargetClassAdapter
{void Request();
}// 适配者类
public class AdapteeClassAdapter
{public void SpecificRequest(){Console.WriteLine("AdapteeClassAdapter: Specific request.");}
}// 适配器类,继承适配者类并实现目标接口
public class ClassAdapter : AdapteeClassAdapter, ITargetClassAdapter
{public void Request(){SpecificRequest();}
}class ProgramClassAdapter
{static void Main(){// 创建类适配器对象ITargetClassAdapter adapter = new ClassAdapter();// 通过适配器调用目标接口方法adapter.Request();}
}

优点

  1. 提高复用性:可以让原本不兼容的类一起工作,使得一些已经存在的类可以被复用,无需对其进行修改。例如,当你有一个旧的库,其接口与新系统不兼容时,使用适配器模式可以将其集成到新系统中。

  2. 灵活性和扩展性:适配器模式符合开闭原则,当需要适配新的类时,只需要创建新的适配器类,而不需要修改现有的代码。

  3. 解耦性:将客户端和适配者解耦,客户端只需要与目标接口交互,而不需要关心适配者的具体实现。

缺点

  1. 增加系统复杂度:引入适配器类会增加系统的类数量和代码复杂度,特别是当存在多个适配器时,可能会使系统变得难以理解和维护。

  2. 过多使用会导致代码混乱:如果过度使用适配器模式,可能会导致系统中存在大量的适配器类,使得代码结构变得混乱,难以把握整体的设计意图。

相关文章:

C#面试常考随笔12:游戏开发中常用的设计模式【C#面试题(中级篇)补充】

C#面试题&#xff08;中级篇&#xff09;&#xff0c;详细讲解&#xff0c;帮助你深刻理解&#xff0c;拒绝背话术&#xff01;-CSDN博客 简单工厂模式 优点&#xff1a; 根据条件有工厂类直接创建具体的产品 客户端无需知道具体的对象名字&#xff0c;可以通过配置文件创建…...

【深度学习入门_机器学习理论】朴素贝叶斯(NaiveBayes)

本部分主要为机器学习理论入门_熟悉朴素贝叶斯算法&#xff0c;书籍参考 “ 统计学习方法&#xff08;第二版&#xff09;”。 学习目标&#xff1a; 熟悉条件概率、先验概率、后验概率、全概率&#xff0c;熟悉朴素贝叶斯算法原理与推判断过程&#xff1b;熟悉参数估计&#…...

docker pull Error response from daemon问题

里面填写 里面解决方案就是挂代理。 以虚拟机为例&#xff0c;将宿主机配置端口设置&#xff0c;https/http端口设为7899 配置虚拟机的http代理&#xff1a; vim /etc/systemd/system/docker.service.d/http-proxy.conf里面填写&#xff0c;wq保存 [Service] Environment…...

javaEE-8.JVM(八股文系列)

目录 一.简介 二.JVM中的内存划分 JVM的内存划分图: 堆区:​编辑 栈区:​编辑 程序计数器&#xff1a;​编辑 元数据区&#xff1a;​编辑 经典笔试题&#xff1a; 三,JVM的类加载机制 1.加载: 2.验证: 3.准备: 4.解析: 5.初始化: 双亲委派模型 概念: JVM的类加…...

25.02.04 《CLR via C#》 笔记 13

核心机制 第二十章 异常和状态管理 什么是异常&#xff1a;异常指成员没有完成它的名称所宣称的行动&#xff1b;异常是程序运行过程中用来表示错误并处理的机制&#xff0c;错误可以是更广义的&#xff0c;包括程序中未捕获的问题或逻辑缺陷。异常处理机制&#xff08;try-c…...

git 项目的更新

更新项目 当自己的本地项目与 远程的github 的仓库已经建立远程连接时&#xff0c; 则直接按照下面的步骤&#xff0c; 将本地的项目代码更新到远程仓库。 # Stage the resolved file git add README.md <file1> <file2># To stage all changes: git add .# Comm…...

【Rust自学】17.3. 实现面向对象的设计模式

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 17.3.1. 状态模式 状态模式(state pattern) 是一种面向对象设计模式&#xff0c;指的是一个值拥有的内部状态由数个状态对象&#xff08…...

51c视觉~CV~合集10

我自己的原文哦~ https://blog.51cto.com/whaosoft/13241694 一、CV创建自定义图像滤镜 热图滤镜 这组滤镜提供了各种不同的艺术和风格化光学图像捕捉方法。例如&#xff0c;热滤镜会将图像转换为“热图”&#xff0c;而卡通滤镜则提供生动的图像&#xff0c;这些图像看起来…...

如何安全地管理Spring Boot项目中的敏感配置信息

在开发Spring Boot应用时&#xff0c;我们经常需要处理一些敏感的配置信息&#xff0c;比如数据库密码、API密钥等。以下是一个最佳实践方案&#xff1a; 1. 创建配置文件 application.yml&#xff08;版本控制&#xff09; spring:datasource:url: ${MYSQL_URL:jdbc:mysql…...

Docker小游戏 | 使用Docker部署2048网页小游戏

Docker小游戏 | 使用Docker部署2048网页小游戏 前言项目介绍项目简介项目预览二、系统要求环境要求环境检查Docker版本检查检查操作系统版本三、部署2048网页小游戏下载镜像创建容器检查容器状态检查服务端口安全设置四、访问2048网页小游戏五、总结前言 在当今快速发展的技术世…...

RabbitMQ深度探索:消息幂等性问题

RabbitMQ 消息自动重试机制&#xff1a; 让我们消费者处理我们业务代码的时候&#xff0c;如果抛出异常的情况下&#xff0c;在这时候 MQ 会自动触发重试机制&#xff0c;默认的情况下 RabbitMQ 时无限次数的重试需要认为指定重试次数限制问题 在什么情况下消费者实现重试策略…...

Linux网络 | 进入数据链路层,学习相关协议与概念

前言&#xff1a;本节内容进入博主讲解的网络层级中的最后一层&#xff1a;数据链路层。 首先博主还是会线代友友们认识一下数据链路层的报文。 然后会带大家重新理解一些概念&#xff0c;比如局域网交换机等等。然后就是ARP协议。 讲完这些&#xff0c; 本节任务就算结束。 那…...

芝法酱学习笔记(2.6)——flink-cdc监听mysql binlog并同步数据至elastic-search和更新redis缓存

一、需求背景 在有的项目中&#xff0c;尤其是进销存类的saas软件&#xff0c;一开始为了快速把产品做出来&#xff0c;并没有考虑缓存问题。而这类软件&#xff0c;有着复杂的业务逻辑。如果想在原先的代码中&#xff0c;添加redis缓存&#xff0c;改动面将非常大&#xff0c…...

JavaScript系列(58)--性能监控系统详解

JavaScript性能监控系统详解 &#x1f4ca; 今天&#xff0c;让我们深入探讨JavaScript的性能监控系统。性能监控对于保证应用的稳定性和用户体验至关重要。 性能监控基础概念 &#x1f31f; &#x1f4a1; 小知识&#xff1a;JavaScript性能监控是指通过收集和分析各种性能指…...

GESP2023年12月认证C++六级( 第三部分编程题(1)闯关游戏)

参考程序代码&#xff1a; #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <string> #include <map> #include <iostream> #include <cmath> using namespace std;const int N 10…...

git 新项目

新项目git 新建的项目如何进行git 配置git git config --global user.name "cc" git config --global user.email ccexample.com配置远程仓库路径 // 添加 git remote add origin http://gogs/cc/mc.git //如果配错了&#xff0c;删除 git remote remove origin初…...

系统URL整合系列视频一(需求方案)

视频 系统URL整合系列视频一&#xff08;需求方案&#xff09; 视频介绍 &#xff08;全国&#xff09;某大型分布式系统Web资源URL整合需求实现方案讲解。当今社会各行各业对软件系统的web资源访问权限控制越来越严格&#xff0c;控制粒度也越来越细。安全级别提高的同时也增…...

Vue.js 使用组件库构建 UI

Vue.js 使用组件库构建 UI 在 Vue.js 项目中&#xff0c;构建漂亮又高效的用户界面&#xff08;UI&#xff09;是很重要的一环。组件库就是你开发 UI 的好帮手&#xff0c;它可以大大提高开发效率&#xff0c;减少重复工作&#xff0c;还能让你的项目更具一致性和专业感。今天…...

计算图 Compute Graph 和自动求导 Autograd | PyTorch 深度学习实战

前一篇文章&#xff0c;Tensor 基本操作5 device 管理&#xff0c;使用 GPU 设备 | PyTorch 深度学习实战 本系列文章 GitHub Repo: https://github.com/hailiang-wang/pytorch-get-started PyTorch 计算图和 Autograd 微积分之于机器学习Computational Graphs 计算图Autograd…...

51单片机入门_05_LED闪烁(常用的延时方法:软件延时、定时器延时;while循环;unsigned char 可以表示的数字是0~255)

本篇介绍编程实现LED灯闪烁&#xff0c;需要学到一些新的C语言知识。由于单片机执行的速度是非常快的&#xff0c;如果不进行延时的话&#xff0c;人眼是无法识别(停留时间要大于20ms)出LED灯是否在闪烁所以需要学习如何实现软件延时。另外IO口与一个字节位的数据对应关系。 文…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

Chrome 浏览器前端与客户端双向通信实战

Chrome 前端&#xff08;即页面 JS / Web UI&#xff09;与客户端&#xff08;C 后端&#xff09;的交互机制&#xff0c;是 Chromium 架构中非常核心的一环。下面我将按常见场景&#xff0c;从通道、流程、技术栈几个角度做一套完整的分析&#xff0c;特别适合你这种在分析和改…...

沙箱虚拟化技术虚拟机容器之间的关系详解

问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西&#xff0c;但是如果把三者放在一起&#xff0c;它们之间到底什么关系&#xff1f;又有什么联系呢&#xff1f;我不是很明白&#xff01;&#xff01;&#xff01; 就比如说&#xff1a; 沙箱&#…...