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

结构型设计模式2

文章目录

享元模式

1、定义与核心思想

(1)定义
  • 享元模式(Flyweight Pattern)是一种结构型设计模式,其核心在于通过共享技术减少对象数量,降低内存消耗,适用于存在大量相似对象的场景。
  • 该模式将对象状态分为内部状态(Intrinsic)和外部状态(Extrinsic),其中内部状态可共享,而外部状态由客户端动态传递。
(2)核心目标
  • 内存优化:减少重复对象的创建。
  • 性能提升:通过共享对象避免重复计算。
(3)适用场景
  • 系统需要创建大量相似对象(如文本编辑器中的字符、游戏中的粒子特效)。
  • 对象的大部分状态可外部化,且外部状态与内部状态分离。
(4)应用场景
  • 图形渲染系统:共享相同的材质和纹理数据,位置和旋转角度作为外部状态。
  • 数据库连接池:复用数据库连接对象,避免频繁创建销毁。
  • 游戏开发:子弹、敌人等大量重复对象的实例共享。
  • 字符串驻留池:.NET 中的字符串驻留机制是享元模式的典型实现。

2、结构与角色

(1)抽象享元(Flyweight Interface)
  • 定义对象的操作接口,通常包含处理外部状态的方法。
public interface IFlyweight
{void Operation(string extrinsicState);
}
(2)具体享元(Concrete Flyweight)
  • 实现抽象接口,存储内部状态(不可变)。
public class ConcreteFlyweight : IFlyweight
{private readonly string _intrinsicState;public ConcreteFlyweight(string intrinsicState){_intrinsicState = intrinsicState;}public void Operation(string extrinsicState){Console.WriteLine($"内部状态: {_intrinsicState}, 外部状态: {extrinsicState}");}
}
(3)享元工厂(Flyweight Factory)
  • 管理共享对象池,确保相同内部状态的对象只创建一次。
public class FlyweightFactory
{private readonly Dictionary<string, IFlyweight> _flyweights = new();public IFlyweight GetFlyweight(string key){if (!_flyweights.ContainsKey(key)){_flyweights[key] = new ConcreteFlyweight(key);}return _flyweights[key];}
}
(4)客户端(Client)
  • 负责维护外部状态并调用享元对象。

3、C# 实现示例

(1)基础案例
  • 场景:模拟文本编辑器中的字符渲染,相同字体的字符共享内部状态(字体、颜色),位置由外部状态决定。
// 抽象享元
public interface ICharacter
{void Draw(int x, int y);
}// 具体享元
public class Character : ICharacter
{private readonly string _font;private readonly string _color;public Character(string font, string color){_font = font;_color = color;}public void Draw(int x, int y){Console.WriteLine($"在位置({x},{y})渲染字体: {_font}, 颜色: {_color}");}
}// 享元工厂
public class CharacterFactory
{private Dictionary<string, ICharacter> _characters = new();public ICharacter GetCharacter(string font, string color){string key = $"{font}_{color}";if (!_characters.ContainsKey(key)){_characters[key] = new Character(font, color);}return _characters[key];}
}// 客户端
class Client
{static void Main(){CharacterFactory factory = new CharacterFactory();// 共享相同字体的字符ICharacter charA = factory.GetCharacter("Arial", "Red");charA.Draw(10, 20);ICharacter charB = factory.GetCharacter("Arial", "Red"); // 复用对象charB.Draw(30, 40);}
}
  • 输出:
在位置(10,20)渲染字体: Arial, 颜色: Red  
在位置(30,40)渲染字体: Arial, 颜色: Red  
(2)关键优化
  • 线程安全:使用 ConcurrentDictionary 管理共享池。
private readonly ConcurrentDictionary<string, Lazy<IFlyweight>> _flyweights = new();
  • 外部状态管理:将可变状态(如位置、大小)通过方法参数传递,而非存储于对象内部。
  • 组合模式扩展:对于复杂对象,可将享元与非享元对象组合使用。
public class CompositeFlyweight : IFlyweight
{private List<IFlyweight> _children = new();public void Add(IFlyweight flyweight) => _children.Add(flyweight);public void Operation(string extrinsicState){foreach (var child in _children)child.Operation(extrinsicState);}
}
(3)扩展:内存池技术
  • 在 C# 中,可通过 ObjectPool 或自定义池实现高效对象复用:
public class ObjectPool<T> where T : new()
{private readonly ConcurrentBag<T> _objects = new();public T GetObject() => _objects.TryTake(out T item) ? item : new T();public void ReturnObject(T item) => _objects.Add(item);
}
(4)最佳实践
  • 设计原则:优先识别可共享的内部状态,避免过度设计。
  • 性能权衡:在内存敏感场景(如嵌入式系统、移动端)优先使用享元模式。
  • 结合其他模式:与工厂模式、组合模式协同解决复杂问题。

4、优缺点分析

(1)优点
  • 内存节省:显著减少对象数量(例如,1000个相同字符只需1个享元对象)。
  • 性能提升:避免重复初始化开销。
(2)缺点
  • 复杂性增加:需明确区分内部与外部状态。
  • 线程安全问题:共享对象需考虑并发访问。
(3)对比其他模式
模式核心区别适用场景
单例模式确保类只有一个实例全局唯一对象(如配置)
工厂模式创建不同类型的对象对象创建逻辑复杂
装饰模式动态添加职责扩展对象功能

代理模式👍

1、定义与核心思想

(1)定义与目的
  • 代理模式(Proxy Pattern)是一种结构型设计模式,通过引入代理对象控制对真实对象的访问,核心在于解耦客户端与目标对象,并添加间接层以增强功能(如权限校验、日志记录、延迟加载等)。
(2)结构与角色
  • 抽象主题(Subject):定义代理与真实对象的公共接口,确保客户端透明调用。
  • 真实主题(Real Subject):实现业务逻辑的核心对象。
  • 代理(Proxy):持有真实对象引用,负责控制访问并扩展功能。
(3)典型场景
  • 远程服务调用(如Web Service、gRPC代理)。
  • 权限控制与安全校验(保护代理)。
  • 延迟加载与资源优化(虚拟代理)。
  • 日志记录与性能监控(动态代理)。

2、C#代码实现

(1)静态代理
  • 实现要点
    • 显式定义代理类,与真实对象共同实现同一接口。
    • 手动添加额外逻辑(如权限检查、日志记录)。
  • 应用场景:权限控制、日志增强等
  • 代码示例(以媒婆代理为例)
// 抽象接口:送礼行为
public interface IGiveGift {void GiveFlowers();void GiveChocolate();
}// 真实对象:追求者
public class Pursuit : IGiveGift {private SchoolGirl girl;public Pursuit(SchoolGirl girl) => this.girl = girl;public void GiveFlowers() => Console.WriteLine($"送花给{girl.Name}");public void GiveChocolate() => Console.WriteLine($"送巧克力给{girl.Name}");
}// 代理对象:媒婆
public class Proxy : IGiveGift {private Pursuit pursuit;public Proxy(SchoolGirl girl) => pursuit = new Pursuit(girl);public void GiveFlowers() {Console.WriteLine("[媒婆日志] 开始送花");pursuit.GiveFlowers();}public void GiveChocolate() {Console.WriteLine("[媒婆日志] 开始送巧克力");pursuit.GiveChocolate();}
}// 客户端调用
SchoolGirl jiaojiao = new SchoolGirl { Name = "李娇娇" };
IGiveGift proxy = new Proxy(jiaojiao);
proxy.GiveFlowers();
(2)虚拟代理(延迟加载)
  • 实现要点
    • 延迟创建高开销对象,仅在首次访问时初始化真实对象。
    • 适用于大文件加载、数据库连接等场景。
  • 代码示例(图片加载代理)
public interface IImage {void Display();
}public class RealImage : IImage {private string _path;public RealImage(string path) {_path = path;LoadFromDisk(); // 高开销操作}public void Display() => Console.WriteLine($"显示图片:{_path}");private void LoadFromDisk() => Console.WriteLine($"加载图片:{_path}");
}public class ProxyImage : IImage {private string _path;private RealImage _realImage;public ProxyImage(string path) => _path = path;public void Display() {if (_realImage == null) {_realImage = new RealImage(_path); // 延迟初始化}_realImage.Display();}
}// 客户端调用
IImage image = new ProxyImage("large_image.jpg");
image.Display(); // 第一次调用时才加载图片
(3)保护代理(权限控制)
  • 实现要点
    • 验证访问权限,限制非法操作。
    • 典型场景:敏感数据访问、API权限校验。
  • 代码示例
public interface ISensitiveData {void AccessData();
}public class SensitiveData : ISensitiveData {public void AccessData() => Console.WriteLine("访问敏感数据");
}public class ProtectionProxy : ISensitiveData {private SensitiveData _data;private string _userRole;public ProtectionProxy(string role) => _userRole = role;public void AccessData() {if (_userRole == "Admin") {if (_data == null) _data = new SensitiveData();_data.AccessData();} else {Console.WriteLine("权限不足!");}}
}// 客户端调用
ISensitiveData proxy = new ProtectionProxy("User");
proxy.AccessData(); // 输出:"权限不足!"
(4)动态代理(运行时生成)
  • 实现要点
    • 通过反射或第三方库(如Castle DynamicProxy)自动生成代理类。
    • 避免静态代理的代码冗余,适用于AOP编程。
  • 示例(使用Castle.Core)
// 定义拦截器
public class LogInterceptor : IInterceptor {public void Intercept(IInvocation invocation) {Console.WriteLine($"[日志] 调用方法:{invocation.Method.Name}");invocation.Proceed();}
}// 生成动态代理
var proxyGenerator = new ProxyGenerator();
var service = proxyGenerator.CreateInterfaceProxyWithTarget<IService>(new ServiceImpl(), new LogInterceptor()
);
service.Execute(); // 输出日志并执行真实方法

3、优缺点分析

(1)优点
  • 解耦客户端与真实对象,扩展性强。
  • 实现权限控制、延迟加载等非业务功能。
(2)缺点
  • 增加系统复杂度,可能影响性能(如动态代理)。
(3)对比其他模式
模式核心区别
装饰器模式增强对象功能,关注添加职责。
适配器模式转换接口,解决兼容性问题。
外观模式封装子系统接口,简化复杂调用流程。

组合模式

1、定义与核心思想

(1)定义
  • 组合模式是一种结构型设计模式,用于将对象组织成树形结构以表示“部分-整体”的层次关系。
  • 其核心思想是通过统一接口处理单个对象(叶子)和组合对象(容器),使客户端无需区分操作目标的具体类型。
(2)核心角色
  • Component(抽象组件):定义所有对象的公共接口,包含管理子组件的方法(如 AddRemove)和操作(如 Display)。
  • Leaf(叶子节点):示不可再分的对象,通常不包含子组件,仅实现操作逻辑。
  • Composite(组合节点):包含子组件的容器对象,实现子组件管理和操作委托。
(3)应用场景
  • 文件系统:文件和文件夹的树形结构是组合模式的典型应用,客户端可统一处理文件的读取、删除等操作。
  • 组织架构:企业组织架构(如公司-部门-员工)可通过组合模式实现层级展示和管理。
  • UI控件树:GUI框架中的容器(Panel)和控件(Button)可统一处理布局和渲染。
  • 菜单系统:多级菜单(主菜单-子菜单-菜单项)的操作可递归执行。

2、C#代码实现

(1)透明模式实现
  • 透明模式下,所有组件(包括叶子)统一实现管理子组件的方法,但叶子节点的相关方法可能为空或抛出异常。
  • 这种设计简化了客户端调用,但可能违反接口隔离原则。
// 抽象组件
public abstract class Component
{public string Name { get; set; }public Component(string name){Name = name;}public abstract void Add(Component component);public abstract void Remove(Component component);public abstract void Display(int depth);
}// 叶子节点(员工)
public class Employee : Component
{public Employee(string name) : base(name) { }public override void Add(Component component){throw new NotSupportedException("叶子节点无法添加子节点");}public override void Remove(Component component){throw new NotSupportedException("叶子节点无法移除子节点");}public override void Display(int depth){Console.WriteLine(new string('-', depth) + Name);}
}// 组合节点(部门)
public class Department : Component
{private List<Component> _children = new List<Component>();public Department(string name) : base(name) { }public override void Add(Component component){_children.Add(component);}public override void Remove(Component component){_children.Remove(component);}public override void Display(int depth){Console.WriteLine(new string('-', depth) + Name);foreach (var child in _children){child.Display(depth + 2);}}
}
(2)安全模式实现
  • 安全模式下,管理子组件的方法仅在组合节点中实现,叶子节点无需支持这些操作。
  • 客户端需明确区分叶子与容器,但更符合接口隔离原则。
// 抽象组件(仅定义操作)
public abstract class Component
{public string Name { get; set; }public Component(string name){Name = name;}public abstract void Display(int depth);
}// 组合节点扩展接口
public interface IComposite
{void Add(Component component);void Remove(Component component);
}// 组合节点(部门)
public class Department : Component, IComposite
{private List<Component> _children = new List<Component>();public Department(string name) : base(name) { }public void Add(Component component){_children.Add(component);}public void Remove(Component component){_children.Remove(component);}public override void Display(int depth){Console.WriteLine(new string('-', depth) + Name);foreach (var child in _children){child.Display(depth + 2);}}
}// 叶子节点(员工)
public class Employee : Component
{public Employee(string name) : base(name) { }public override void Display(int depth){Console.WriteLine(new string('-', depth) + Name);}
}
(3)扩展讨论
  • 递归遍历优化:对于深层嵌套结构,可采用缓存、迭代器或备忘录模式优化递归性能。
  • 组合模式与数据绑定:在MVVM框架中,组合模式可结合数据绑定实现动态UI更新。
(4)公司组织架构案例
  • 以下是一个完整的企业组织架构实现示例:
// 抽象组件
public abstract class OrganizationComponent
{public string Name { get; set; }public OrganizationComponent(string name){Name = name;}public abstract void Add(OrganizationComponent component);public abstract void Remove(OrganizationComponent component);public abstract void Display(int depth);public abstract void SendNotice(string message);
}// 叶子节点(员工)
public class Employee : OrganizationComponent
{public Employee(string name) : base(name) { }public override void Add(OrganizationComponent component){throw new NotSupportedException("员工无法添加下属");}public override void Remove(OrganizationComponent component){throw new NotSupportedException("员工无法移除下属");}public override void Display(int depth){Console.WriteLine($"{new string('-', depth)}员工:{Name}");}public override void SendNotice(string message){Console.WriteLine($"员工[{Name}]收到通知:{message}");}
}// 组合节点(部门)
public class Department : OrganizationComponent
{private List<OrganizationComponent> _children = new List<OrganizationComponent>();public Department(string name) : base(name) { }public override void Add(OrganizationComponent component){_children.Add(component);}public override void Remove(OrganizationComponent component){_children.Remove(component);}public override void Display(int depth){Console.WriteLine($"{new string('-', depth)}部门:{Name}");foreach (var child in _children){child.Display(depth + 2);}}public override void SendNotice(string message){Console.WriteLine($"部门[{Name}]发送通知:{message}");foreach (var child in _children){child.SendNotice(message);}}
}// 客户端调用
class Program
{static void Main(){// 构建组织架构var root = new Department("总公司");root.Add(new Employee("CEO"));var hrDept = new Department("人力资源部");hrDept.Add(new Employee("HR经理"));hrDept.Add(new Employee("招聘专员"));root.Add(hrDept);var techDept = new Department("技术部");techDept.Add(new Employee("CTO"));var devTeam = new Department("开发组");devTeam.Add(new Employee("开发工程师A"));devTeam.Add(new Employee("开发工程师B"));techDept.Add(devTeam);root.Add(techDept);// 显示架构root.Display(1);// 发送通知root.SendNotice("本周五召开全员会议");}
}

3、优缺点分析

(1)优点
  • 统一接口:客户端无需区分叶子与容器,简化调用逻辑。
  • 灵活扩展:新增组件类型无需修改现有代码,符合开闭原则。
  • 树形结构支持:天然支持递归遍历和复杂层级操作。
(2)缺点
  • 接口冗余:透明模式可能导致叶子节点实现无意义的方法。
  • 性能开销:递归遍历可能影响性能,需谨慎设计层级深度。
  • 复杂性增加:设计初期需明确对象层次,可能增加系统复杂度。
(3)组合模式 vs 装饰器模式
  • 组合模式:处理对象间的层次结构(部分-整体)。
  • 装饰器模式:动态扩展对象功能(附加职责)。
http://www.dtcms.com/a/589264.html

相关文章:

  • 怎么做ppt教程网站灰色项目源码
  • 蛋白质内在无序区域(IDR)预测benchmark
  • 【TIDE DIARY 7】临床指南转公众版系统升级详解
  • STM32百问百答:从硬件到软件全面解析
  • MyBatis-Plus 框架设计模式全景解析
  • 创建型设计模式1
  • AI大数据在医疗健康中的应用与发展趋势
  • 网站规划与开发实训室建设方案个人如何做微商城网站
  • 标准 Python 项目结构
  • 【开发者导航】面向快速模型演示与轻量交互开发的可视化工具:Gradio
  • Vue 项目实战《尚医通》,首页常见科室静态搭建,笔记16
  • 东莞热的建设网站网页视频怎么下载到电脑上
  • 区块链论文速读 CCF A--USENIX Security 2025(4)
  • PHM数据集轴承寿命预测!Transformer-GRU轴承寿命预测MATLAB代码实现
  • 网站错误代码301建设网站如何给页面命名
  • FreeRTOS 学习:(十六)可调用 FromISR 相关 API 函数的中断优先级范围
  • 织梦网站修改使用教程郑州高端网站建设怎么样
  • GPU集群poc测试
  • 操作系统(12)进程描述与控制--进程概述(2)
  • 数据库库、表的创建及处理
  • 空间矢量脉宽调制(Space Vector Pulse Width Modulation)SVPWM基础
  • 链接的迷雾:odr、弱符号与静态库的三国杀
  • Vite + React 项目启动深度踩坑指南
  • 回收网站建设短网址生成器免费
  • Servlet 的 URLPattern配置
  • 传奇购买域名做网站一个网站的渠道网络建设
  • MATLAB中显示X、Y、Z三个方向信号的时频特征,使用时频分析方法
  • 构建AI智能体:八十九、Encoder-only与Decoder-only模型架构:基于ModelScope小模型的实践解析
  • SpringMVC快速入门
  • CPU亲和性深度实践:从基础原理到Intel大小核架构优化