结构型设计模式之装饰模式

article/2025/6/27 5:37:10

文章目录

    • 1. 装饰模式概述
    • 2. 模式结构
    • 3. 装饰模式与继承的区别
    • 4. 装饰模式的优缺点
      • 优点
      • 缺点
    • 5. C#代码示例
      • 5.1 基本示例 - 饮料与调料
      • 5.2 更复杂的示例 - 文本格式化器
    • 6. C#中装饰器模式的实际应用
      • 6.1 C# I/O 流处理
      • 6.2 ASP.NET Core 中间件
    • 7. 装饰模式与其他设计模式的比较
    • 8. 装饰模式的实现步骤和最佳实践
      • 最佳实践
    • 9. 装饰模式在实际项目中的注意事项
    • 10. 实际案例分析 - 日志系统
    • 11. 总结
    • 学习资源

1. 装饰模式概述

装饰模式(Decorator Pattern)是一种结构型设计模式,它允许向一个现有的对象添加新的功能,同时又不改变其结构。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

装饰模式的核心思想是:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式比继承更为灵活,符合"开闭原则"。

2. 模式结构

装饰模式主要包含以下几个核心角色:

Component
Operation()
ConcreteComponent
Operation()
Decorator
Component component
Operation()
ConcreteDecoratorA
addedState
Operation()
AddedBehavior()
ConcreteDecoratorB
Operation()
AddedBehavior()
  • 抽象组件(Component):定义一个对象接口,可以给这些对象动态添加职责
  • 具体组件(ConcreteComponent):定义一个对象,可以给这个对象添加一些职责
  • 抽象装饰器(Decorator):继承自抽象组件,并持有一个抽象组件的引用,它的主要职责是为Component添加新的责任
  • 具体装饰器(ConcreteDecorator):具体的装饰器类,负责向组件添加新的职责

3. 装饰模式与继承的区别

装饰模式和继承都是为了扩展对象的功能,但它们有着本质的不同:

特性装饰模式继承
扩展方式组合关系,动态扩展静态扩展,编译时确定
灵活性高,可以在运行时动态添加/删除功能低,继承关系在编译时就确定
类爆炸问题避免了类爆炸容易导致类爆炸
耦合度低耦合,遵循依赖倒置原则高耦合,子类依赖父类实现
复杂度相对较高,需要更多的对象交互相对简单,直接复用父类代码

装饰模式使用组合而非继承来扩展功能,遵循了"多用组合,少用继承"的设计原则,避免了继承带来的类爆炸问题,同时提供了更大的灵活性。

4. 装饰模式的优缺点

优点

  1. 扩展性强:可以在不修改现有对象结构的情况下,动态地添加功能
  2. 符合开闭原则:对扩展开放,对修改关闭
  3. 比继承更加灵活:可以通过不同装饰器的排列组合,创造出不同行为的组合
  4. 避免类爆炸:使用多个小类进行组合,而不是创建大量功能不同的子类
  5. 可以动态添加或删除责任:在运行时根据需求增减功能

缺点

  1. 增加系统复杂度:需要创建大量小对象,加大了系统的复杂度
  2. 可能产生很多小对象:装饰模式要求被装饰的组件和所有装饰器必须是同一类型
  3. 不容易理解:多层装饰器的调试可能比较困难,需要剥离多层装饰来分析问题
  4. 可能增加对象创建的复杂度:需要实例化并管理多个对象

5. C#代码示例

5.1 基本示例 - 饮料与调料

以下是一个咖啡店饮料系统的示例,使用装饰模式来添加不同的调料:

using System;// 抽象组件类 - 饮料
public abstract class Beverage
{protected string description = "未知饮料";// 获取描述public virtual string GetDescription(){return description;}// 计算价格(抽象方法,由具体子类实现)public abstract double Cost();
}// 具体组件类 - 浓缩咖啡
public class Espresso : Beverage
{// 构造函数中设置描述public Espresso(){description = "浓缩咖啡";}// 实现Cost方法返回价格public override double Cost(){return 19.0;}
}// 具体组件类 - 黑咖啡
public class HouseBlend : Beverage
{public HouseBlend(){description = "黑咖啡";}public override double Cost(){return 15.0;}
}// 抽象装饰器类 - 调料
public abstract class CondimentDecorator : Beverage
{// 所有调料装饰器必须重新实现GetDescription方法public abstract override string GetDescription();
}// 具体装饰器类 - 牛奶
public class Milk : CondimentDecorator
{// 持有一个被装饰对象的引用private Beverage beverage;// 构造函数需要一个饮料作为参数public Milk(Beverage beverage){this.beverage = beverage;}// 在原有描述的基础上添加牛奶描述public override string GetDescription(){return beverage.GetDescription() + ",加牛奶";}// 在原有价格的基础上加上牛奶的价格public override double Cost(){return beverage.Cost() + 2.0;}
}// 具体装饰器类 - 摩卡
public class Mocha : CondimentDecorator
{private Beverage beverage;public Mocha(Beverage beverage){this.beverage = beverage;}public override string GetDescription(){return beverage.GetDescription() + ",加摩卡";}public override double Cost(){return beverage.Cost() + 3.0;}
}// 具体装饰器类 - 奶泡
public class Whip : CondimentDecorator
{private Beverage beverage;public Whip(Beverage beverage){this.beverage = beverage;}public override string GetDescription(){return beverage.GetDescription() + ",加奶泡";}public override double Cost(){return beverage.Cost() + 1.5;}
}// 客户端代码
public class CoffeeShop
{public static void Main(string[] args){// 点一杯浓缩咖啡Beverage beverage1 = new Espresso();Console.WriteLine($"{beverage1.GetDescription()} ¥{beverage1.Cost()}");// 点一杯黑咖啡,加双倍摩卡和奶泡Beverage beverage2 = new HouseBlend();beverage2 = new Mocha(beverage2);     // 包装一次beverage2 = new Mocha(beverage2);     // 包装两次beverage2 = new Whip(beverage2);      // 包装三次Console.WriteLine($"{beverage2.GetDescription()} ¥{beverage2.Cost()}");// 点一杯浓缩咖啡,加牛奶和奶泡Beverage beverage3 = new Espresso();beverage3 = new Milk(beverage3);beverage3 = new Whip(beverage3);Console.WriteLine($"{beverage3.GetDescription()} ¥{beverage3.Cost()}");}
}/* 输出:
浓缩咖啡 ¥19
黑咖啡,加摩卡,加摩卡,加奶泡 ¥22.5
浓缩咖啡,加牛奶,加奶泡 ¥22.5
*/

5.2 更复杂的示例 - 文本格式化器

下面是一个使用装饰模式实现的文本格式化系统,可以动态地给文本添加不同的格式化效果:

using System;
using System.Text;// 抽象组件 - 文本接口
public interface IText
{string GetContent();
}// 具体组件 - 普通文本
public class PlainText : IText
{private string content;public PlainText(string content){this.content = content;}public string GetContent(){return content;}
}// 抽象装饰器 - 文本格式化装饰器
public abstract class TextDecorator : IText
{protected IText text;public TextDecorator(IText text){this.text = text;}// 默认实现是委托给包装的对象public virtual string GetContent(){return text.GetContent();}
}// 具体装饰器 - 粗体装饰器
public class BoldDecorator : TextDecorator
{public BoldDecorator(IText text) : base(text) {}// 重写GetContent方法,添加粗体标记public override string GetContent(){// 在原有内容的基础上添加粗体标记return $"<b>{text.GetContent()}</b>";}
}// 具体装饰器 - 斜体装饰器
public class ItalicDecorator : TextDecorator
{public ItalicDecorator(IText text) : base(text) {}public override string GetContent(){return $"<i>{text.GetContent()}</i>";}
}// 具体装饰器 - 下划线装饰器
public class UnderlineDecorator : TextDecorator
{public UnderlineDecorator(IText text) : base(text) {}public override string GetContent(){return $"<u>{text.GetContent()}</u>";}
}// 具体装饰器 - 颜色装饰器
public class ColorDecorator : TextDecorator
{private string color;// 构造器需要额外的颜色参数public ColorDecorator(IText text, string color) : base(text){this.color = color;}public override string GetContent(){return $"<span style=\"color:{color}\">{text.GetContent()}</span>";}
}// 客户端代码
public class TextEditor
{public static void Main(string[] args){// 创建一个普通文本IText text = new PlainText("Hello, Decorator Pattern!");Console.WriteLine("普通文本: " + text.GetContent());// 添加粗体格式IText boldText = new BoldDecorator(text);Console.WriteLine("粗体文本: " + boldText.GetContent());// 添加斜体格式IText italicText = new ItalicDecorator(text);Console.WriteLine("斜体文本: " + italicText.GetContent());// 组合多种格式:粗体 + 斜体IText boldItalicText = new BoldDecorator(new ItalicDecorator(text));Console.WriteLine("粗斜体文本: " + boldItalicText.GetContent());// 组合多种格式:红色 + 粗体 + 下划线IText complexText = new ColorDecorator(new BoldDecorator(new UnderlineDecorator(text)), "red");Console.WriteLine("复杂格式文本: " + complexText.GetContent());}
}/* 输出:
普通文本: Hello, Decorator Pattern!
粗体文本: <b>Hello, Decorator Pattern!</b>
斜体文本: <i>Hello, Decorator Pattern!</i>
粗斜体文本: <b><i>Hello, Decorator Pattern!</i></b>
复杂格式文本: <span style="color:red"><b><u>Hello, Decorator Pattern!</u></b></span>
*/

6. C#中装饰器模式的实际应用

6.1 C# I/O 流处理

.NET框架中的I/O类就是装饰模式的典型应用。以下是一个使用C#流的示例:

using System;
using System.IO;
using System.Text;public class StreamExample
{public static void Main(string[] args){// 创建文件using (FileStream fileStream = new FileStream("example.txt", FileMode.Create)){// 装饰文件流,添加缓冲功能using (BufferedStream bufferedStream = new BufferedStream(fileStream)){// 再次装饰,添加文本写入功能using (StreamWriter writer = new StreamWriter(bufferedStream, Encoding.UTF8)){// 使用最终装饰好的对象写入文本writer.WriteLine("这是一个装饰模式的示例。");writer.WriteLine("我们使用了多个装饰器来增强FileStream的功能:");writer.WriteLine("1. BufferedStream添加了缓冲功能");writer.WriteLine("2. StreamWriter添加了文本写入功能");}// 离开using块时,各个流会按顺序关闭}}Console.WriteLine("文件已成功写入,现在读取它:");// 读取文件using (FileStream fileStream = new FileStream("example.txt", FileMode.Open)){// 装饰文件流,添加缓冲功能using (BufferedStream bufferedStream = new BufferedStream(fileStream)){// 再次装饰,添加文本读取功能using (StreamReader reader = new StreamReader(bufferedStream, Encoding.UTF8)){// 读取并输出所有文本string content = reader.ReadToEnd();Console.WriteLine(content);}}}}
}

在这个例子中,我们可以看到多个装饰器如何层层包装原始的FileStream对象,每一层都添加了新的功能:

  • FileStream:提供对文件的基本读写功能
  • BufferedStream:添加了缓冲功能,提高I/O性能
  • StreamWriter/StreamReader:添加了文本写入/读取功能

6.2 ASP.NET Core 中间件

ASP.NET Core的中间件管道也是装饰模式的一个应用实例。每个中间件都可以处理请求,然后将请求传递给下一个中间件。

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Threading.Tasks;public class Startup
{public void ConfigureServices(IServiceCollection services){// 配置服务}// 配置HTTP请求管道public void Configure(IApplicationBuilder app, IWebHostEnvironment env){// 异常处理中间件app.UseExceptionHandler("/Home/Error");// 静态文件中间件app.UseStaticFiles();// 路由中间件app.UseRouting();// 认证中间件app.UseAuthentication();// 授权中间件app.UseAuthorization();// 自定义中间件app.Use(async (context, next) =>{// 请求前的处理Console.WriteLine($"请求开始: {context.Request.Path}");// 调用下一个中间件await next();// 请求后的处理Console.WriteLine($"请求结束: {context.Response.StatusCode}");});// 端点中间件app.UseEndpoints(endpoints =>{endpoints.MapControllerRoute(name: "default",pattern: "{controller=Home}/{action=Index}/{id?}");});}
}

在这个例子中,每个中间件都可以视为一个装饰器,它们共同装饰HTTP请求和响应,添加各种功能,如异常处理、验证、授权等。

7. 装饰模式与其他设计模式的比较

装饰模式与其他几种常见的设计模式有一些相似之处,但也有明显的区别:

设计模式主要目的与装饰模式的区别
代理模式控制对对象的访问代理模式注重控制对对象的访问,装饰模式注重动态添加功能
适配器模式使不兼容的接口能够一起工作适配器改变接口,装饰器保持原接口不变
组合模式将对象组合成树形结构组合模式构建复杂结构,装饰模式递增地添加功能
策略模式定义一系列算法,使它们可以互换策略模式关注于算法切换,装饰模式关注于功能叠加

8. 装饰模式的实现步骤和最佳实践

实现装饰模式一般遵循以下步骤:

  1. 创建抽象组件接口/类:定义所有具体组件和装饰器的公共接口
  2. 实现具体组件类:实现抽象组件接口的基础功能
  3. 创建抽象装饰器类:继承抽象组件,并持有一个抽象组件的引用
  4. 实现具体装饰器类:继承抽象装饰器类,并添加新的功能
  5. 客户端使用:客户端代码组合使用具体组件和各种装饰器

最佳实践

  1. 保持接口一致性:装饰器应该与它所装饰的组件具有相同的接口,以保证透明性
  2. 单一职责原则:每个装饰器应专注于添加单一的职责
  3. 避免装饰器爆炸:太多的装饰器会使系统变得复杂,应适度使用
  4. 考虑使用工厂或构建器模式:使用工厂或构建器模式可以简化复杂装饰器的创建
  5. 注意装饰顺序:有时装饰器的应用顺序会影响最终行为

9. 装饰模式在实际项目中的注意事项

  1. 接口的稳定性:如果接口经常变化,那么所有装饰器都需要更新,造成维护困难

  2. 性能影响:每个装饰器都是一个对象,过多的装饰器可能导致性能下降和内存占用增加

  3. 调试复杂度:多层装饰可能导致调试困难,因为需要逐层检查装饰器链

  4. 文档和命名:为了提高代码可读性,应为每个装饰器提供清晰的文档和命名

  5. 与依赖注入框架的结合:在使用依赖注入框架时,需要特别注意装饰器的注册和解析方式

10. 实际案例分析 - 日志系统

下面是一个使用装饰模式实现的可扩展日志系统:

using System;
using System.IO;// 抽象组件 - 日志接口
public interface ILogger
{void Log(string message);
}// 具体组件 - 基础控制台日志
public class ConsoleLogger : ILogger
{public void Log(string message){Console.WriteLine($"[INFO] {DateTime.Now}: {message}");}
}// 具体组件 - 基础文件日志
public class FileLogger : ILogger
{private string filePath;public FileLogger(string filePath){this.filePath = filePath;}public void Log(string message){using (StreamWriter writer = File.AppendText(filePath)){writer.WriteLine($"[INFO] {DateTime.Now}: {message}");}}
}// 抽象装饰器 - 日志装饰器
public abstract class LoggerDecorator : ILogger
{protected ILogger logger;public LoggerDecorator(ILogger logger){this.logger = logger;}// 默认实现是委托给被装饰对象public virtual void Log(string message){logger.Log(message);}
}// 具体装饰器 - 时间戳装饰器
public class TimestampDecorator : LoggerDecorator
{public TimestampDecorator(ILogger logger) : base(logger) { }public override void Log(string message){string timestampedMessage = $"[Timestamp: {DateTime.Now.Ticks}] {message}";logger.Log(timestampedMessage);}
}// 具体装饰器 - 错误级别装饰器
public class ErrorLevelDecorator : LoggerDecorator
{private LogLevel level;public enum LogLevel{INFO,WARNING,ERROR,CRITICAL}public ErrorLevelDecorator(ILogger logger, LogLevel level) : base(logger){this.level = level;}public override void Log(string message){string leveledMessage = $"[{level}] {message}";logger.Log(leveledMessage);}
}// 具体装饰器 - 加密装饰器
public class EncryptionDecorator : LoggerDecorator
{public EncryptionDecorator(ILogger logger) : base(logger) { }// 简单的模拟加密方法private string Encrypt(string message){// 实际应用中会使用真正的加密算法return $"ENCRYPTED({message})";}public override void Log(string message){string encryptedMessage = Encrypt(message);logger.Log(encryptedMessage);}
}// 客户端代码
public class LoggingSystem
{public static void Main(string[] args){// 1. 基础控制台日志ILogger consoleLogger = new ConsoleLogger();consoleLogger.Log("这是一条基础日志消息");// 2. 添加错误级别的控制台日志ILogger errorConsoleLogger = new ErrorLevelDecorator(consoleLogger, ErrorLevelDecorator.LogLevel.ERROR);errorConsoleLogger.Log("这是一条错误日志消息");// 3. 基础文件日志ILogger fileLogger = new FileLogger("log.txt");// 4. 带时间戳和错误级别的文件日志ILogger decoratedFileLogger = new TimestampDecorator(new ErrorLevelDecorator(fileLogger, ErrorLevelDecorator.LogLevel.WARNING));decoratedFileLogger.Log("这是一条带时间戳和警告级别的文件日志消息");// 5. 带加密的文件日志ILogger secureLogger = new EncryptionDecorator(fileLogger);secureLogger.Log("这是一条加密的日志消息");// 6. 复杂组合:带加密、时间戳和错误级别的控制台日志ILogger complexLogger = new EncryptionDecorator(new TimestampDecorator(new ErrorLevelDecorator(consoleLogger, ErrorLevelDecorator.LogLevel.CRITICAL)));complexLogger.Log("这是一条高度安全的关键错误日志消息");}
}

这个例子展示了如何使用装饰模式创建一个灵活的日志系统,可以动态地组合各种日志功能。

11. 总结

装饰模式是一种灵活的结构型设计模式,它通过将对象包装在装饰器类中,以便动态地添加新行为。它遵循"开闭原则",使我们能够在不修改现有代码的情况下扩展对象的功能。

装饰模式的核心优势在于:

  1. 比静态继承更灵活,提供了更多的扩展性
  2. 避免了类爆炸问题
  3. 可以在运行时动态组合不同的行为
  4. 符合单一职责原则,每个装饰器专注于一个功能

装饰模式在实际开发中有广泛的应用,特别是在需要动态扩展对象功能的场景中,如I/O处理、UI组件、权限系统等。

当我们需要在不修改现有代码的情况下为对象添加新的责任时,应该考虑使用装饰模式,它提供了一种灵活且可扩展的解决方案。

学习资源

  1. Design Patterns: Elements of Reusable Object-Oriented Software - GoF经典著作
  2. Head First Design Patterns - 生动易懂的设计模式入门书籍
  3. Refactoring.Guru - Decorator Pattern
  4. C# Design Pattern Essentials
  5. Microsoft Learn - Design Patterns

在这里插入图片描述


http://www.hkcw.cn/article/XUsEgNlrns.shtml

相关文章

开发的几种格式,TCP的十个重要机制

自定义协议中&#xff0c; 我们有几种常见的数据格式&#xff1a; 1.xml 通过标签来组织数据 请求&#xff1a; 优势&#xff1a; 让数据的可读性变更好了 劣势&#xff1a; 标签非常繁琐&#xff0c;传输的时候也占用更多网络带宽&#xff08;maven会使用xml来管理项目配…

ASP.NET Core OData 实践——Lesson9绑定和未绑定的Function和Action(C#)

大纲 概念支持的接口主要模型设计控制器设计数据源FunctionBound FunctionUnbound Function重载&#xff08;overload&#xff09; ActionBound ActionUnbound Action重载&#xff08;overload&#xff09;Bound ActionUnbound Action 主程序服务文档模型元文档 代码地址参考资…

描述性统计——让数据说话

第03篇&#xff1a;描述性统计——让数据说话 写在前面&#xff1a;大家好&#xff0c;我是蓝皮怪&#xff01;前两篇我们聊了统计学的基本概念和数据类型&#xff0c;这一篇我们要正式进入数据分析的第一步——描述性统计。别被名字吓到&#xff0c;其实就是用一组数字&#x…

【MySQL基础】库的操作:创建、删除与管理数据库

MySQL学习&#xff1a; https://blog.csdn.net/2301_80220607/category_12971838.html?spm1001.2014.3001.5482 前言&#xff1a; 在上一篇我们已经讲解了数据库的基本内容&#xff0c;相信大家对数据库已经有了一些自己的理解&#xff0c;从这篇开始我们就开始正式进入如何…

国足抵达雅加达备战世预赛 力争两连胜晋级希望

中国男足国家队于6月2日晚抵达印度尼西亚首都雅加达,准备参加5日举行的2026美加墨世界杯亚洲区预选赛18强赛第9轮对阵印尼队的比赛。当地时间晚上10时30分,中国队在主教练伊万科维奇的带领下走出雅加达苏加诺-哈达国际机场,随后乘坐大巴前往酒店。伊万科维奇表示,中国队在…

中国龙舟文化“划”向全世界

央视网消息:这个端午假期,热气腾腾的“端午经济”成为消费活力升级的缩影。“国潮”风引领文化消费新风尚,传统文化元素与现代技术交融,非遗体验“烟火气”满满,打造出独特的“国潮端午”氛围,持续火热的国潮消费也一路“火”到了海外。这段时间,在义乌国际商贸城做3D打…

马斯克宣布离职:不想为政府政策负责 “政府效率部”成替罪羊

埃隆马斯克在接受美国哥伦比亚广播公司采访时提到,他并不想公开反对美国政府,但也不愿意为政府所做的一切承担责任。他表示,他领导的“政府效率部”成了所有问题的替罪羊,无论是真是假的裁员都归咎于这个部门。马斯克还表示,他对国会共和党正在讨论的数万亿美元减税与支出…

韩国5名候选人竞逐总统 李在明领跑民调

韩国第21届总统大选于当地时间6月3日6时正式开始,全国共设有14295个投票站。没有参加提前投票的选民凭本人身份证件前往指定投票站即可参加投票,投票将于当日20时结束。本次大选共有7位候选人进行了登记,但其中两位先后宣布退出,并表示支持国民力量党候选人金文洙。因此,选…

学者:李在明若胜将大幅调整外交政策 韩国大选临近决策点

韩国总统大选即将于3日迎来正式投票。根据选前多项民调结果,共同民主党候选人李在明仍以明显优势领先国民力量党的金文洙和改革新党的李俊锡。金文洙与李俊锡合并无望的情况下,李在明距离总统宝座仅一步之遥。2日举行的选前最后一场记者会几乎成为了李在明的“总统政策说明会…

2025/6月最新Cursor(0.50.5版本)一键自动更换邮箱无限续杯教程

使用前检查&#xff1a; 使用前请先看左下角&#xff0c;是否获取到Cursor的版本号 如果没有请先在 功能页面 -→ 自定义Cursor路径 选择你Cursor的安装的路径&#xff0c;并开启后重启YCursor&#xff0c;获取到版本后才能正常使用功能 检查软件左下角的权限标识是否为绿色 如…

算法:二分查找

1.二分查找 704. 二分查找 - 力扣&#xff08;LeetCode&#xff09; 二分查找算法要确定“二段性”&#xff0c;时间复杂度为O(lonN)。为了防止数据溢出&#xff0c;所以求mid时要用防溢出的方式。 class Solution { public:int search(vector<int>& nums, int tar…

Elasticsearch 读写流程深度解析

在数据驱动的数字化浪潮中&#xff0c;Elasticsearch 凭借其毫秒级搜索响应与水平扩展能力&#xff0c;已成为现代数据架构的核心引擎。本文将深入剖析其读写流程的设计思想、实现细节与工程权衡&#xff0c;揭示这一分布式系统的精妙架构。 一、 架构基石&#xff1a;分布式设…

2024年第十五届蓝桥杯Scratch10月stema选拔赛真题——数字卡片排序

2024年第十五届蓝桥杯Scratch10月stema选拔赛真题——数字卡片排序 题目可点下面去处&#xff0c;支持在线编程~ 数字卡片排序_scratch_少儿编程题库学习中心-嗨信奥 程序演示可下下面去处&#xff0c;支持获取素材和源码~ 数字卡片排序-scratch作品-少儿编程题库学习中心-嗨…

基于遥感图像深度学习的海洋测深

知识星球&#xff1a;数据书局。打算通过知识星球将这些年积累的知识、经验分享出来&#xff0c;让各位在数据治理、数据分析的路上少走弯路&#xff0c;另外星球也方便动态更新最近的资料&#xff0c;提供各位一起讨论数据的小圈子 1. 摘要 沿海开发和规划面临的问题&#…

《使命召唤》防线失守:系列多款游戏被破解,黑客公开源代码 堡垒首次被突破

每当一款新游戏在PC平台发售,如果未使用Denuvo加密技术,破解者们就会竞相争夺首个破解该作品的机会。例如,《漫威蜘蛛侠 2》和《最后生还者 2》分别在发售后不到两分钟和一天内被破解。长期以来,《使命召唤》系列因其独特的数字版权管理技术和始终在线的网络连接而被视为难…

男子端午节爬野山迷路,还执意自己找路!27人冒雨搜山救援 公益救援彰显大爱

5月31日端午节,在北京房山的一处野山中,一名男子登山迷路却不想麻烦救援队,坚持要自己摸索下山。男子曾向警方询问下山道路,但拒绝了蓝天救援队的帮助。然而不久后,他再次联系救援队请求援助,称自己过于自信,但找不到路。尽管被困男子最初未请求救援,房山蓝天救援队出于…

中山漫展 女童暴露服装引争议

中山漫展 女童暴露服装引争议!6月1日,在广东中山漫展现场,观众看到两名女童身着暴露服装参加付费直播活动,纷纷提出质疑。微信公众号“中山博览中心”5月27日发文称,5月31日至6月1日10点-17点,将在中山博览中心前厅和综合展厅举行“2025中山AS24端午动漫嘉年华”活动。文…

前端八股之CSS

CSS 盒子模型深度解析与实战 一、盒子模型核心概念 Box-sizing CSS 中的 box-sizing 属性定义了引擎应该如何计算一个元素的总宽度和总高度 语法&#xff1a; box-sizing: content-box|border-box|inherit:content-box 默认值&#xff0c;元素的 width/height 不包含paddi…

渊龙靶场-sql注入(数字型注入)

1.开局请求抓包 测试点如上图&#xff0c;测试注入&#xff0c;存在注入。 2.查询列数 我们再查他多少列 ,最后测试为为2列。 3.查询回显位 发现均可以回显 4.查询表 插入语句查询表和数据库 union select database(),group_concat(table_name) FROM information_schema.t…

Linux内核体系结构简析

1.Linux内核 1.1 Linux内核的任务 从技术层面讲&#xff0c;内核是硬件和软件之间的一个中间层&#xff0c;作用是将应用层序的请求传递给硬件&#xff0c;并充当底层驱动程序&#xff0c;对系统中的各种设备和组件进行寻址。从应用程序的角度讲&#xff0c;应用程序与硬件没有…