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

行为型设计模式1

文章目录

观察者模式👍

1、定义与核心思想

(1)定义
  • 观察者模式(Observer Pattern)是一种行为型设计模式,用于定义对象间的一对多依赖关系。
  • 当一个对象(称为主题/被观察者)的状态发生变化时,所有依赖它的对象(称为观察者)会自动收到通知并更新。
(2)核心角色
  • Subject(主题):维护观察者列表,提供注册、注销方法,并在状态变化时通知观察者。
  • Observer(观察者):定义更新接口,用于接收主题状态变化的通知。
(3)适用场景
  • 需要动态解耦对象间的依赖关系(如UI事件响应、消息发布-订阅系统)。

2、C#代码实现

(1)基于接口的传统实现
    1. 定义接口
// 观察者接口
public interface IObserver {void Update(string message);
}// 主题接口
public interface ISubject {void Attach(IObserver observer);void Detach(IObserver observer);void Notify(string message);
}
    1. 具体实现类
// 具体主题(例如新闻发布中心)
public class NewsAgency : ISubject {private List<IObserver> _observers = new List<IObserver>();public void Attach(IObserver observer) => _observers.Add(observer);public void Detach(IObserver observer) => _observers.Remove(observer);public void Notify(string message) {foreach (var observer in _observers) {observer.Update(message);}}// 模拟状态变化public void PublishNews(string news) {Notify($"最新新闻:{news}");}
}// 具体观察者(例如新闻订阅用户)
public class NewsSubscriber : IObserver {public void Update(string message) {Console.WriteLine($"收到新闻:{message}");}
}
  • 优点:符合设计模式经典结构,适用于复杂场景。
  • 缺点:需要手动管理观察者列表。
(2)基于事件与委托的简化实现
  • C#的事件机制天然支持观察者模式,无需显式定义接口。
public class NewsAgency {// 定义事件委托public event Action<string> NewsPublished;// 触发事件public void PublishNews(string news) {NewsPublished?.Invoke($"最新新闻:{news}");}
}// 观察者订阅事件
public class NewsSubscriber {public NewsSubscriber(NewsAgency agency) {agency.NewsPublished += OnNewsReceived;}private void OnNewsReceived(string message) {Console.WriteLine($"收到新闻:{message}");}
}
  • 优点:代码简洁,无需手动管理观察者列表。
  • 缺点:耦合度稍高,难以动态注销特定观察者。

3、进阶实现与框架支持

(1)使用.NET内置的IObservable接口
public class NewsAgency : IObservable<string> {private List<IObserver<string>> _observers = new List<IObserver<string>>();public IDisposable Subscribe(IObserver<string> observer) {_observers.Add(observer);return new Unsubscriber(_observers, observer);}private class Unsubscriber : IDisposable {private List<IObserver<string>> _observers;private IObserver<string> _observer;public Unsubscriber(List<IObserver<string>> observers, IObserver<string> observer) {_observers = observers;_observer = observer;}public void Dispose() {if (_observer != null) _observers.Remove(_observer);}}public void PublishNews(string news) {foreach (var observer in _observers) {observer.OnNext(news);}}
}
  • 特点:支持资源释放管理(通过IDisposable),适用于需要严格生命周期控制的场景。
(2)应用场景与实战案例
  • 案例一:气象监测系统(经典场景)
// 主题:气象站
public class WeatherStation : ISubject {private List<IObserver> _observers = new List<IObserver>();private float _temperature;public void SetTemperature(float temp) {_temperature = temp;Notify();}public void Attach(IObserver observer) => _observers.Add(observer);public void Detach(IObserver observer) => _observers.Remove(observer);public void Notify() {foreach (var observer in _observers) {observer.Update(_temperature);}}
}// 观察者:温度显示设备
public class TemperatureDisplay : IObserver {public void Update(float temperature) {Console.WriteLine($"当前温度:{temperature}°C");}
}
  • 案例二:动态事件分发(游戏开发)
    • 在Unity中,观察者模式常用于处理角色状态变化和UI更新
    • 优势:通过事件解耦游戏逻辑与UI更新
// 主题:玩家生命值
public class PlayerHealth : MonoBehaviour {public event Action<int> OnHealthChanged;private int _currentHealth = 100;public void TakeDamage(int damage) {_currentHealth -= damage;OnHealthChanged?.Invoke(_currentHealth);}
}// 观察者:UI血条
public class HealthUI : MonoBehaviour {[SerializeField] private Slider _healthSlider;public void Bind(PlayerHealth health) {health.OnHealthChanged += UpdateHealthBar;}private void UpdateHealthBar(int health) {_healthSlider.value = health;}
}
(3)最佳实践
  • 选择实现方式 :简单场景优先使用事件与委托;复杂场景或需跨组件交互时使用接口或IObservable。
  • 避免内存泄漏:在观察者生命周期结束时显式注销事件订阅。
  • 线程安全:多线程环境中需对观察者列表进行锁保护。

4、优缺点分析

(1)优点
  • 松耦合:主题与观察者独立变化,易于扩展新观察者。
  • 动态订阅:支持运行时动态注册或注销观察者。
  • 广播通信:一次状态变化可通知多个对象。
(2)缺点
  • 性能开销:大量观察者或高频通知可能导致性能问题。
  • 循环依赖风险:若观察者与主题相互引用,可能引发内存泄漏。
(3)对比其他模式
模式核心区别适用场景
观察者模式一对多通知,动态订阅机制事件驱动系统、UI更新
发布-订阅模式引入中间代理(如消息队列)分布式系统、跨进程通信
中介者模式通过中介协调对象交互,减少直接依赖复杂对象间的集中式通信管理

策略模式👍

1、定义与核心思想

(1)定义
  • 策略模式(Strategy Pattern)是一种行为型设计模式,其核心思想是将算法族封装成独立的类,使其可以互相替换,从而让算法独立于客户端而变化。
  • 通过解耦算法定义与使用,策略模式能显著提升代码的可维护性、扩展性和复用性。
(2)核心价值
  • 消除条件分支:通过多态替代冗长的if-elseswitch逻辑,简化复杂条件判断。
  • 动态切换行为:运行时灵活选择算法,无需修改客户端代码。
  • 开闭原则:新增策略无需改动现有逻辑,仅需扩展新类。
(3)应用场景
  • 支付方式选择:如支付宝、微信、信用卡的动态切换。
  • 数据验证规则:不同表单字段的校验逻辑分离。
  • 游戏AI行为:NPC根据环境切换移动或攻击策略。
  • 日志记录策略:本地存储、远程API、数据库日志的灵活切换。
  • 电商促销规则:满减、折扣、积分组合
  • 金融系统中的费率计算:不同地区、用户等级
  • 游戏中的技能释放逻辑:近战、远程、魔法策略

2、结构与角色

(1)抽象策略(IStrategy)
  • 定义所有算法的公共接口(如Calculate方法)。
public interface IStrategy 
{void Execute();
}
(2)具体策略(ConcreteStrategy)
  • 实现接口的具体算法,例如折扣策略、加密算法等。
public class DiscountStrategy : IStrategy 
{public void Execute() {Console.WriteLine("执行8折优惠策略");}
}
(3)上下文(Context)
  • 持有策略对象的引用,负责调用算法,并允许动态切换策略。
public class PaymentContext 
{private IStrategy _strategy;public void SetStrategy(IStrategy strategy) => _strategy = strategy;public void ExecutePayment() {_strategy?.Execute();}
}

3、C#代码实现

(1)基础实现
  • 场景示例:电商促销系统支持多种折扣策略(满减、折扣、积分)。
// 抽象策略
public interface IPromotionStrategy 
{decimal ApplyDiscount(decimal originalPrice);
}// 具体策略:满减
public class FullReductionStrategy : IPromotionStrategy 
{public decimal ApplyDiscount(decimal price) {return price >= 300 ? price - 100 : price;}
}// 上下文
public class PromotionContext 
{private IPromotionStrategy _strategy;public void SetStrategy(IPromotionStrategy strategy) => _strategy = strategy;public decimal ApplyPromotion(decimal price) => _strategy.ApplyDiscount(price);
}// 客户端调用
var context = new PromotionContext();
context.SetStrategy(new FullReductionStrategy());
var finalPrice = context.ApplyPromotion(500); // 输出400
(2)工厂模式结合
  • 优化场景:通过工厂自动创建策略,减少客户端与策略类的耦合。
public static class StrategyFactory 
{public static IPromotionStrategy Create(string type) {return type switch {"FullReduction" => new FullReductionStrategy(),"Discount" => new DiscountStrategy(0.8m),_ => throw new ArgumentException("无效策略类型")};}
}// 客户端调用
var strategy = StrategyFactory.Create("Discount");
context.SetStrategy(strategy);
(3)依赖注入优化
  • 使用DI容器(如ASP.NET Core)
  • 通过构造函数注入策略,实现更高层次的解耦。
services.AddTransient<IPromotionStrategy, FullReductionStrategy>();
services.AddTransient<PromotionContext>();
(4)个人所得税计算案例
public abstract class Tax 
{protected decimal Rate;protected decimal QuickDeduction;public virtual decimal Calculate(decimal income) => income * Rate - QuickDeduction;
}public class Level3Tax : Tax 
{public Level3Tax() { Rate = 0.1m; QuickDeduction = 210; }
}// 上下文通过收入自动选择税率策略

4、扩展与优化

(1)委托与Lambda简化
  • 利用C#的委托特性,可将策略模式简化为函数式实现
public class PaymentContext 
{private Func<decimal, decimal> _strategy;public void SetStrategy(Func<decimal, decimal> strategy) => _strategy = strategy;public decimal Apply(decimal price) => _strategy?.Invoke(price) ?? price;
}// 使用
context.SetStrategy(p => p * 0.8m);
(2)策略自动注册
  • 通过反射动态加载策略类
var strategies = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IStrategy))).ToDictionary(t => t.Name.Replace("Strategy", ""));
(3)组合策略模式
  • 多个策略组合实现复杂逻辑(如折扣+满减)
public class CompositeStrategy : IPromotionStrategy 
{private readonly List<IPromotionStrategy> _strategies;public CompositeStrategy(params IPromotionStrategy[] strategies) => _strategies = strategies.ToList();public decimal ApplyDiscount(decimal price) {return _strategies.Aggregate(price, (current, strategy) => strategy.ApplyDiscount(current));}
}
(4)最佳实践
  • 单一职责:每个策略类仅封装一个算法。
  • 避免滥用:简单条件判断无需过度设计为策略模式。
  • 性能考量:高频调用场景中,委托或字典查找可能优于接口多态。

5、优缺点分析

(1)优点
  • 算法可独立演化,符合开闭原则
  • 消除复杂条件分支,代码更简洁
  • 便于单元测试(每个策略可单独测试)
(2)缺点
  • 策略类数量可能爆炸式增长
  • 客户端需了解所有策略类型
  • 策略间共享数据可能增加耦合
(3)对比其他模式
模式区别
工厂模式工厂关注对象创建,策略关注行为选择
状态模式状态模式处理对象内部状态转换,策略模式主动选择算法
模板方法模板方法通过继承实现算法框架,策略通过组合动态替换

命令模式

1、定义与核心思想

(1)定义
  • 命令模式(Command Pattern)是一种行为型设计模式,其核心在于将请求封装为独立对象,实现请求的发起者(Invoker)与执行者(Receiver)解耦。
  • 通过参数化、队列化、撤销/重做等特性,提升代码的可维护性和扩展性。
(2)核心价值
  • 解耦性:调用者无需依赖具体执行逻辑。
  • 扩展性:新增命令只需继承接口,符合开闭原则。
  • 事务支持:支持操作序列的原子执行与回滚。
(3)角色与结构
  • 角色定义
角色职责说明
Command声明执行操作的抽象接口(如Execute()
ConcreteCommand实现Command接口,绑定接收者并调用其方法
Receiver实际执行业务逻辑的对象(如文件操作、设备控制)
Invoker触发命令执行的对象(如按钮、遥控器)
Client创建命令对象并关联接收者与调用者
  • UML结构图
Client → Invoker  
Client → ConcreteCommand  
ConcreteCommand → Receiver  
Command ← ConcreteCommand  
Invoker → Command
(4)典型应用场景
场景示例
GUI操作按钮点击事件绑定不同命令(如保存、打印)
事务管理数据库操作的回滚与重做
任务队列异步任务调度(如后台批量处理)
日志与审计记录用户操作历史

2、基础实现

// 1. 接收者(实际执行操作)
public class Light {public void TurnOn() => Console.WriteLine("灯已打开");public void TurnOff() => Console.WriteLine("灯已关闭");
}// 2. 命令接口
public interface ICommand {void Execute();
}// 3. 具体命令类
public class LightOnCommand : ICommand {private Light _light;public LightOnCommand(Light light) => _light = light;public void Execute() => _light.TurnOn();
}public class LightOffCommand : ICommand {private Light _light;public LightOffCommand(Light light) => _light = light;public void Execute() => _light.TurnOff();
}// 4. 调用者(触发命令)
public class RemoteControl {private ICommand _command;public void SetCommand(ICommand command) => _command = command;public void PressButton() => _command?.Execute();
}// 5. 客户端配置
public class Client {public static void Main() {Light light = new Light();ICommand onCommand = new LightOnCommand(light);RemoteControl remote = new RemoteControl();remote.SetCommand(onCommand);remote.PressButton(); // 输出:灯已打开}
}

3、高级扩展

(1)撤销与重做
  • 实现思路:
    • ICommand接口中增加Undo()方法。
    • 维护操作历史栈(Stack<ICommand>)。
using System;
using System.Collections.Generic;// 接收者:文件系统操作
public class FileSystemReceiver {public void CreateFile(string path) => Console.WriteLine($"创建文件:{path}");public void DeleteFile(string path) => Console.WriteLine($"删除文件:{path}");
}// 命令接口
public interface IFileCommand {void Execute();void Undo();
}// 具体命令:创建文件
public class CreateFileCommand : IFileCommand {private FileSystemReceiver _receiver;private string _path;public CreateFileCommand(FileSystemReceiver receiver, string path) {_receiver = receiver;_path = path;}public void Execute() => _receiver.CreateFile(_path);public void Undo() => _receiver.DeleteFile(_path);
}// 调用者:支持撤销的操作管理器
public class FileOperationManager {private Stack<IFileCommand> _history = new Stack<IFileCommand>();public void ExecuteCommand(IFileCommand cmd) {cmd.Execute();_history.Push(cmd);}public void UndoLast() {if (_history.Count > 0)_history.Pop().Undo();}
}// 客户端
public class Client {public static void Main() {FileSystemReceiver fs = new FileSystemReceiver();FileOperationManager manager = new FileOperationManager();IFileCommand createCmd = new CreateFileCommand(fs, "test.txt");manager.ExecuteCommand(createCmd);  // 输出:创建文件:test.txtmanager.UndoLast();                 // 输出:删除文件:test.txt}
}
(2)宏命令
  • 应用场景:一键执行多个操作(如启动电脑时同时打开IDE、数据库服务)
public class MacroCommand : ICommand {private List<ICommand> _commands = new List<ICommand>();public void AddCommand(ICommand cmd) => _commands.Add(cmd);public void Execute() {foreach (var cmd in _commands)cmd.Execute();}
}
(3)最佳实践
  • 避免过度设计:简单操作无需强制使用命令模式。
  • 结合DI容器:通过依赖注入管理命令对象的生命周期。
  • 性能优化:高频操作慎用历史记录,防止内存溢出。

4、对比其他模式

模式区别点协作场景
策略模式关注算法替换,命令模式关注操作封装命令对象可使用策略选择具体执行逻辑
备忘录模式用于保存对象状态,支持回滚结合实现多层撤销功能
责任链模式请求由多个处理器依次处理命令队列中按链式执行命令

状态模式👍

1、定义与核心思想

(1)定义
  • 状态模式(State Pattern) 是一种行为型设计模式,允许对象在其内部状态改变时改变其行为,使得对象看起来像修改了自身的类。
  • 其核心思想是将状态抽象为独立类,通过封装状态的行为与转换逻辑,实现复杂条件分支的简化。
(2)模式结构
  • Context(上下文):持有当前状态对象的引用,定义客户端接口并委托状态相关行为给具体状态类。例如电梯控制类或订单管理系统。
  • State(抽象状态):定义状态接口,声明不同状态下的行为方法。
  • ConcreteState(具体状态):实现抽象状态接口,定义当前状态下的具体行为,并可能触发状态转换。
  • 类图示例:
Context → State
↑
ConcreteStateA, ConcreteStateB, ...
(3)适用场景
  • 对象行为依赖状态:如游戏角色状态(站立、奔跑、跳跃)。
  • 复杂的状态转换:如工单审批流程、设备控制(电梯、交通灯)。
  • 减少重复条件判断:当多个操作需要根据状态执行不同逻辑时。

2、C#代码实现

(1)电灯开关控制
  • 场景:电灯有“开”和“关”两种状态,每次按下开关切换状态并执行对应操作。
  • 关键点:上下文类 LightContext 委托行为给当前状态对象,状态切换由具体状态类触发
// 抽象状态接口
public interface ILightState
{void PressSwitch(LightContext context);
}// 具体状态:开灯
public class LightOnState : ILightState
{public void PressSwitch(LightContext context){Console.WriteLine("关闭电灯");context.SetState(new LightOffState());}
}// 具体状态:关灯
public class LightOffState : ILightState
{public void PressSwitch(LightContext context){Console.WriteLine("打开电灯");context.SetState(new LightOnState());}
}// 上下文类
public class LightContext
{private ILightState _currentState;public LightContext(ILightState initialState){_currentState = initialState;}public void SetState(ILightState state){_currentState = state;}public void PressSwitch(){_currentState.PressSwitch(this);}
}// 客户端调用
var light = new LightContext(new LightOffState());
light.PressSwitch(); // 输出:打开电灯
light.PressSwitch(); // 输出:关闭电灯
(2)电梯状态管理
  • 场景:电梯有“开门”“关门”“运行”“停止”四种状态,不同状态下操作逻辑不同。
  • 优势:通过状态类封装行为,避免了大量 if-else 判断逻辑。
// 抽象状态
public abstract class ElevatorState
{public abstract void OpenDoor(ElevatorContext context);public abstract void CloseDoor(ElevatorContext context);public abstract void Run(ElevatorContext context);public abstract void Stop(ElevatorContext context);
}// 具体状态:停止状态
public class StoppedState : ElevatorState
{public override void OpenDoor(ElevatorContext context){Console.WriteLine("电梯门已打开");context.SetState(new OpenedState());}// 其他方法实现类似...
}// 上下文类
public class ElevatorContext
{private ElevatorState _currentState;public ElevatorContext(){_currentState = new StoppedState(); // 初始状态}public void SetState(ElevatorState state){_currentState = state;}public void OpenDoor() => _currentState.OpenDoor(this);public void CloseDoor() => _currentState.CloseDoor(this);// 其他方法委托...
}
(3)订单状态流转
  • 场景:电商订单可能经历“待支付→已支付→已发货→已完成”等状态,不同状态下操作(如退款、发货)的合法性不同。
  • 应用场景:状态模式在订单系统、审批流程等需要复杂状态管理的场景中广泛应用。
// 抽象状态
public abstract class OrderState
{public virtual void Pay(OrderContext context) => throw new InvalidOperationException();public virtual void Ship(OrderContext context) => throw new InvalidOperationException();// 其他方法...
}// 具体状态:待支付
public class PendingPaymentState : OrderState
{public override void Pay(OrderContext context){Console.WriteLine("订单已支付");context.SetState(new PaidState());}
}// 上下文类
public class OrderContext
{private OrderState _currentState;public OrderContext(){_currentState = new PendingPaymentState();}public void SetState(OrderState state){_currentState = state;}public void Pay() => _currentState.Pay(this);public void Ship() => _currentState.Ship(this);
}

3、进阶应用与框架集成

(1)在游戏开发中的应用
  • 示例:角色状态机(站立、攻击、受伤)
  • 关键点:通过状态模式实现平滑的行为切换,适合复杂角色行为管理
public class PlayerContext
{private IPlayerState _currentState;public void SetState(IPlayerState state){_currentState?.Exit(this); // 旧状态退出逻辑_currentState = state;_currentState.Enter(this); // 新状态进入逻辑}public void Update() => _currentState?.Execute(this);
}// 具体状态:攻击状态
public class AttackState : IPlayerState
{public void Enter(PlayerContext context) => Console.WriteLine("进入攻击状态");public void Execute(PlayerContext context) { /* 攻击逻辑 */ }public void Exit(PlayerContext context) => Console.WriteLine("退出攻击状态");
}
(2)与有限状态机结合
  • 状态模式常被用于实现有限状态机,通过状态转移表管理转换条件
  • 优势:通过表格驱动的方式简化状态转移逻辑
// 状态转移表
public class StateTransition
{public State CurrentState { get; }public Event Trigger { get; }public State NextState { get; }public StateTransition(State current, Event trigger, State next){CurrentState = current;Trigger = trigger;NextState = next;}
}// 在上下文中维护转移表
public class FSMManager
{private Dictionary<StateTransition, Action> _transitions = new();public void AddTransition(State current, Event trigger, State next, Action action){_transitions.Add(new StateTransition(current, trigger, next), action);}public void HandleEvent(Event trigger){var transition = new StateTransition(_currentState, trigger);if (_transitions.TryGetValue(transition, out var action)){action();_currentState = transition.NextState;}}
}
(3)最佳实践
  • 何时使用状态模式:
    • 行为随状态频繁变化。
    • 需要避免多层嵌套的条件分支。
  • 最佳实践:
    • 单一职责原则:每个状态类只关注自身行为。
    • 利用框架:如 Spring Statemachine 或 .NET 的 Stateless 库简化实现。
    • 单元测试:为每个状态编写独立测试用例,确保转换逻辑正确。
  • 代码完整性与可维护性:
    • 通过依赖注入管理状态对象,提升可测试性。
    • 使用枚举或常量定义状态类型,避免硬编码。

3、优缺点分析

(1)优点
  • 消除条件分支:通过多态代替 if-else,代码更清晰。
  • 高扩展性:新增状态只需添加新类,符合开闭原则。
  • 职责分离:状态行为封装在独立类中,便于维护。
(2)缺点及解决方案
  • 类爆炸:状态过多时,类的数量可能急剧增长。
    • 解决方案:合并相似状态或使用组合模式。
  • 跨状态依赖:某些行为可能涉及多个状态的协作。
    • 解决方案:通过中介者模式协调状态。
  • 内存管理:频繁创建状态对象可能导致性能问题。
    • 解决方案:使用对象池或享元模式复用状态实例。
(3)状态模式 vs 策略模式
  • 状态模式:状态改变由上下文或具体状态类触发,状态间存在转换逻辑。
  • 策略模式:策略切换由客户端主动设置,策略之间独立。
http://www.dtcms.com/a/589566.html

相关文章:

  • MATLAB实现白噪声与色噪声仿真
  • 甘德县公司网站建设工业设计公司如何运营
  • JAVA-Redis上
  • 免费空间 上传网站虚拟主机推荐
  • mysql配置主从同步
  • 基于SpringBoot+Vue+协同过滤算法的在线旅游系统
  • 【高并发服务器:HTTP应用】十六、HttpContext上下文模块 HttpServer服务器模块 服务器测试
  • 河南科兴建设有限公司网站茂名住房证书城乡建设局官方网站
  • MySQL JSON查询与索引
  • claude code 自定义命令
  • NET_CAPABILITY_VALIDATED 检测android外网是否可用
  • Gin使用
  • SpringAI整合deepseek的一个简单入门案例
  • 突破智能体训练效率瓶颈:Tree Training如何通过共享前缀重用实现3.9倍加速?
  • Java面试题及答案整理( 2025年11月更新版,持续更新...)
  • 定制营销型网站公司色目人
  • 网站普查建设背景网站推广建议
  • 做网站永久嘟嘟浏览器
  • PS1模拟器 DuckStation更新最新版整合 下载即玩 附PS1Bios/游戏/金手指 安卓版+电脑版
  • Java复习事务相关 mysql事务隔离级别 spring事务的传播机制 2025年11月9日
  • 做网站公司排行榜洛阳做网站公司电话
  • 如何发布网站站长是什么职位
  • Vue基本路由
  • 基于springboot的作业管理系统设计与实现
  • Tauri开发手记——1.开发环境
  • 天翼云 ECS 弹性云主机的IP地址无法访问,无法访问 ECS 的网站,解决方案(随手记)
  • 名费网站制作视频教程淘宝代运营公司哪家好
  • 【开题答辩全过程】以 基于springboot美食分享网站为例,包含答辩的问题和答案
  • 福永自适应网站建智能建站系统官网
  • 【FPGA+DSP系列】——MATLAB simulink仿真整流电路