装饰器模式和 AOP 面向切片编程(设计模式与开发实践 P15)

文章目录

    • 示例
    • AOP

很多时候我们不希望一个类变得非常庞大,生来就包含很多职责。装饰器模式可以动态地给某个对象添加职责,而不会影响从这个类中派生的其他对象

为什么不用继承解决这个问题呢?如果用继承有可能会创造出数量庞大的子类,而如果把子类的属性变成装饰器,就可以灵活自由地组合了,就像天冷了要穿一件衣服等等

示例

从结构上看,Attack 方法进入了一个包装链,先执行火焰技能,再执行了闪电技能

// 定义游戏角色接口
interface ICharacter
{void Attack();
}// 实现游戏角色类
class Character : ICharacter
{public void Attack(){Console.WriteLine("角色进行普通攻击!");}
}// 装饰器基类
abstract class CharacterDecorator : ICharacter
{protected ICharacter character;public CharacterDecorator(ICharacter character){this.character = character;}public virtual void Attack(){character.Attack();}
}// 具体装饰器类:添加火焰技能
class FireDecorator : CharacterDecorator
{public FireDecorator(ICharacter character) : base(character){}public override void Attack(){base.Attack();Console.WriteLine("释放火焰技能!");}
}// 具体装饰器类:添加闪电技能
class LightningDecorator : CharacterDecorator
{public LightningDecorator(ICharacter character) : base(character){}public override void Attack(){base.Attack();Console.WriteLine("释放闪电技能!");}
}class Program
{static void Main(string[] args){// 创建基本角色ICharacter character = new Character();// 添加火焰技能character = new FireDecorator(character);// 添加闪电技能character = new LightningDecorator(character);// 角色进行攻击character.Attack();// 输出结果:// 角色进行普通攻击!// 释放火焰技能!// 释放闪电技能!}
}

AOP

在这里我们使用了 C# 的 PostSharp 包,创建了方法切面监听

当 Attack 执行时,会引发 OnEntry 和 OnExit 生命周期

在分离业务代码和数据统计代码中, AOP 十分有效!

using PostSharp.Aspects;
using System;// 日志记录切面
[Serializable]
public class LogAspect : OnMethodBoundaryAspect
{public override void OnEntry(MethodExecutionArgs args){Console.WriteLine($"[Log] Entering {args.Method.Name}");}public override void OnExit(MethodExecutionArgs args){Console.WriteLine($"[Log] Exiting {args.Method.Name}");}
}// 游戏角色类
public class Character
{[LogAspect] // 应用日志记录切面public void Attack(){Console.WriteLine("Character attacking!");}
}// 使用 AOP 的游戏示例
class Program
{static void Main(string[] args){Character character = new Character();character.Attack();// 输出结果:// [Log] Entering Attack// Character attacking!// [Log] Exiting Attack}
}

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

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

相关文章

聚观早报 | 首个“5G-A智慧家庭”发布;李鹏称5G-A是5G发展选择

【聚观365】10月12日消息 首个“5G-A智慧家庭”发布 李鹏称5G-A是5G发展的自然选择 新版努比亚Z50S Pro开售 英特尔锐炫A580显卡全球同步上市 vivo X100系列年底登场 首个“5G-A智慧家庭”发布 在全球移动宽带论坛(MBBF2023)期间,du联合…

这些负载均衡都解决哪些问题?服务、网关、NGINX

这篇文章解答一下群友的一系列提问: 在微服务项目中,有服务的负载均衡、网关的负载均衡、Nginx的负载均衡,这几个负载均衡分别用来解决什么问题呢? 在微服务项目中,服务的负载均衡、网关的负载均衡和Nginx的负载均衡都…

04_学习springdoc与oauth结合_简述

文章目录 1 前言2 基本结构3 需要做的配置 简述4 需要做的配置 详述4.1 backend-api-gateway 的配置4.1.1 application.yml 4.2 backend-film 的配置4.2.1 pom.xml 引入依赖4.2.2 application.yml 的配置4.2.3 Spring Security 资源服务器的配置类 MyResourceServerConfig4.2.4…

uniapp iosApp H5+本地文件操作(写入修改删除等)

h5 地址 html5plus 以csv文件为例,写入读取保存修改删除文件内容,传输文件等 1.save 文件保存 function saveCsv(data,pathP,path){// #ifdef APP-PLUSreturn new Promise((resolve, reject) > {plus.io.requestFileSystem( plus.io.PUBLIC_DOCUMEN…

WIN32API之PIPE管道

管道是进程用于通信的共享内存的一部分。 创建管道的过程是 管道服务器。 连接到管道的进程是 管道客户端。 一个进程将信息写入管道,另一个进程从管道读取信息。 本概述介绍如何创建、管理和使用管道。 命名管道是用于管道服务器与一个或多个管道客户端之间通信的…

vue打印功能

安装 vue3-print-nb yarn add vue3-print-nb //或 npm install vue3-print-nbmain.js中引入 vue3-print-nb import { createApp } from vue; import App from ./App.vue; const app createApp(App); // 打印插件 import print from vue3-print-nb app.use(print) //页面内引…

【Docker 内核详解】namespace 资源隔离(一):进行 namespace API 操作的 4 种方式

namespace 资源隔离(一):进行 namespace API 操作的 4 种方式 1.通过 clone() 在创建新进程的同时创建 namespace2.查看 /proc/[pid]/ns 文件3.通过 setns() 加入一个已经存在的 namespace4.通过 unshare() 在原先进程上进行 namespace 隔离5…

Webapck 解决:[webpack-cli] Error: Cannot find module ‘vue-loader/lib/plugin‘ 的问题

1、问题描述: 其一、报错为: [webpack-cli] Error: Cannot find module vue-loader/lib/plugin 中文为: [webpack-cli] 错误:找不到模块“vue-loader/lib/plugin” 其二、问题描述为: 在项目打包的时候 npm run …

c++视觉图像----扩充边界

图像扩充边界 #include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp>int main() {// 读取图像cv::Mat image cv::imread("1.jpg", cv::IMREAD_COLOR);if (image.empty()) {std::cerr << "Could not open or find the imag…

Java项目调用Python脚本(基于idea)

前期准备 1.首先需要在本地环境中安装配置python环境 Python(含PyCharm及配置)下载安装以及简单使用(Idea) 博主本次使用python版本为py3.7.3 2.idea安装python插件 位置&#xff1a;File->Settings->Plugins->python->安装后重启即可 3.引入jython依赖 &l…

力扣 -- 1312. 让字符串成为回文串的最少插入次数

解题步骤&#xff1a; 参考代码&#xff1a; class Solution { public:int minInsertions(string s) {int ns.size();vector<vector<int>> dp(n,vector<int>(n));//无需初始化//填表for(int in-1;i>0;i--){for(int ji;j<n;j){//状态转移方程if(s[i]s[…

如何在 Spring Boot 中进行数据备份

在Spring Boot中进行数据备份 数据备份是确保数据安全性和可恢复性的关键任务之一。Spring Boot提供了多种方法来执行数据备份&#xff0c;无论是定期备份数据库&#xff0c;还是将数据导出到外部存储。本文将介绍在Spring Boot应用程序中进行数据备份的不同方法。 方法1: 使用…

【深度学习实验】循环神经网络(一):循环神经网络(RNN)模型的实现与梯度裁剪

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入必要的工具包 1. 数据处理 2. rnn 测试 3. grad_clipping 4. 代码整合 经验是智慧之父&#xff0c;记忆是智慧之母。 ——谚语 一、实验介绍 本实验介绍了一个简单的循环神经网络…

如何优化前端图像和多媒体资源?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

电子书制作软件Vellum mac中文版特点

Vellum mac是一款专业的电子书制作软件&#xff0c;它可以帮助用户将文本文件转换为高质量的电子书&#xff0c;支持多种格式&#xff0c;包括EPUB、MOBI、PDF等。Vellum具有直观的用户界面和易于使用的工具&#xff0c;可以让用户快速地创建和发布电子书。 Vellum mac软件特点…

追求极致性能!Qwik 1.0版本发布

前言 偶然发现 Qwik 这个 Node.js 后端框架&#xff0c;感觉非常新奇&#xff0c;它构建的网站&#xff0c;能够在谷歌的网站评测工具中跑出100分满分的成绩&#xff0c;而且还是移动端&#xff08;一般情况下&#xff0c;移动端分值要低于PC端&#xff09;&#xff01;不得不…

IDEA XML文件里写SQL比较大小条件

背景 最近开发的时候&#xff0c;有一个需求的查询需要支持范围查询[a,b)&#xff0c;并且查询的结果要求查询的范围含头端点不含尾端点。因为between…and…查询的范围是含头含尾的&#xff0c;因而不能使用。 因此打算直接使用>和<来比较实现&#xff0c;使用>的时…

【Redis】Set集合内部编码方式

内部编码 集合类型的内部编码有两种&#xff1a; intset&#xff08;整数集合&#xff09;&#xff1a;当集合中的元素都是整数并且元素的个数⼩于set-max-intset-entries配置&#xff08;默认512个&#xff09;时&#xff0c;Redis会选⽤intset来作为集合的内部实现&#xf…

与艺术同频!卡萨帝在海外崭露头角

在品牌全球化步伐日益加快的当下&#xff0c;高端品牌如何真正实现业务全球化、品牌全球化乃至用户圈层全球化&#xff1f; 作为国际高端家电引领者&#xff0c;卡萨帝今年以来在全球范围内展开了一系列的品牌布局活动。1月&#xff0c;卡萨帝于巴基斯坦召开品牌发布会&#x…

hyperf框架WebSocket 服务

1&#xff1a;安装 composer require hyperf/websocket-server2&#xff1a;配置 Server 修改 config/autoload/server.php&#xff0c;增加以下配置。 return [servers > [[name > ws,type > Server::SERVER_WEBSOCKET,host > 0.0.0.0,port > 9502,sock_typ…