使用 Scrutor 快速实现“装饰者模式”

装饰者模式介绍

装饰器模式(Decorator Pattern)是在不改变原类和使用继承的情况下,动态地给一个对象添加一些额外的职责。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

可以在如下使用场景中使用装饰器模式:

  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

  • 需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。

  • 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。

Demo

假设,我们使用IRepository接口的实现类Repository进行数据库访问:

public interface IUserRepository
{User Get(int Id);
}public class UserRepository : IUserRepository
{public User Get(int Id){Console.WriteLine("访问数据库");//模拟数据库访问return new User(Id, "My IO");}
}

现在有一个新的需求:要求增加缓存功能,即先从缓存获取数据,缓存不存在再访问数据库。

有几种方法可以做到这一点:

  1. 修改业务逻辑,在访问Get前读取缓存;

  2. 使用面向切面(AOP)模式,在调用Get方法时注入读取缓存逻辑;

  3. 修改UserRepository实现缓存功能;

  4. 继承UserRepository类,在派生类中实现缓存功能;

  5. 使用装饰器模式封装UserRepository类,在新的UserRepositoryDecorator类中嵌入实现缓存功能;

在这里,我们使用装饰器模式:

internal class UserRepositoryCacheDecorator : IUserRepository
{private readonly IUserRepository _userRepository;public UserRepositoryCacheDecorator(IUserRepository userRepository){_userRepository = userRepository;}public User Get(int Id){Console.WriteLine("访问缓存");return _userRepository.Get(Id);}
}
  • 首先,我们还是实现与UserRepository类相同的IUserRepository接口;

  • 其次,我们将IUserRepository接口注入到构造函数中;

  • 最后,在Get方法中,我们再次调用注入的接口的Get方法,它应该调用UserRepository类的实现。

显然,如果还是按普通方式进行依赖注入,将不可能成功:

builder.Services.AddTransient<IUserRepository, UserRepository>();builder.Services.AddTransient<IUserRepository, UserRepositoryCacheDecorator>();

d85cd4879d85791e3d69299ea4272846.png

这时,我们可以引用 Nuget 包Scrutor,然后使用它提供的Decorate方法:

builder.Services.AddTransient<IUserRepository, UserRepository>();builder.Services.Decorate<IUserRepository, UserRepositoryCacheDecorator>();

现在再运行,你将看到装饰器模式已经实现了:

3d66247eeba99001cdaf4b765e8b67dd.png

结论

可以添加多个装饰,为原来的功能增加不同的职责,而仅需的操作,就是调用Decorate方法进行注册:

builder.Services.Decorate<IUserRepository, UserRepositoryCacheDecorator>();builder.Services.Decorate<IUserRepository, UserRepositoryLogDecorator>();

添加微信号【MyIO666】,邀你加入技术交流群

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

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

相关文章

各个 Android Gradle 插件版本所需的 Gradle 版本

下表列出了各个 Android Gradle 插件版本所需的 Gradle 版本。 要获得最佳性能&#xff0c;您应该使用 Gradle 和插件这两者的最新版本。 插件版本所需的 Gradle 版本1.0.0 - 1.1.32.2.1 - 2.31.2.0 - 1.3.12.2.1 - 2.91.5.02.2.1 - 2.132.0.0 - 2.1.22.10 - 2.132.1.3 - 2.2…

JS时间戳和时间互转

https://www.cnblogs.com/nield-bky/p/6040853.html http://blog.csdn.net/csdn565973850/article/details/73838583 时间转时间戳&#xff1a; javascript获得时间戳的方法有四种&#xff0c;都是通过实例化时间对象 new Date() 来进一步获取当前的时间戳1.var timestamp1 Da…

C语言试题157之从键盘输入一个字符串,将小写字母全部转换成大写字母,然后输出到一个磁盘文件“test”中保存。 输入的字符串以!结束

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目:从键盘输入一个字符串,将小…

【ArcGIS微课1000例】0001:添加XY数据(Add XY data)生成shp

用过CASS的人都知道&#xff0c;野外数字测图得到的点数据&#xff08;平面坐标&#xff09;可以直接在CASS中展点&#xff0c;进一步绘制地形图。那么&#xff0c;带有坐标的数据能不能在ArcGIS中实现点图层的生成呢&#xff1f;答案是必须的&#xff01; 本文以气象台站Excel…

算法导论--广度优先搜索和深度优先搜索

广度优先搜索 在给定图G(V,E)和一个特定的源顶点s的情况下&#xff0c;广度优先搜索系统地探索G中的边&#xff0c;以期“发现”可从s 到达的所有顶点&#xff0c;并计算s 到所有这些可达顶点之间的距离&#xff08;即最少的边数&#xff09;。该搜索算法同时还能生成一棵根为s…

动手学 docker

背景动手学 docker最近&#xff0c;终于完成了 动手学 docker 系列的编写。动手学 docker 是 动手学系列 的首个系列。如果反馈的效果不错&#xff0c;后续还将推出 动手学 devops动手学 kubernetes动手学 istio 等系列。动手学系列 的构思来源于 李沐 老师的 动手学深度学习 。…

Linux零基础入学之1-1课程介绍了解RHEL7安装RHEL7

【本节内容】* 课程介绍* RHEL7了解* RHEL7.2的安装* 实战&#xff1a;组装服务器【Linux介绍】服务器种类&#xff1a;刀片式、塔式&#xff08;机架式&#xff09;1U&#xff1a;4.45cm 三指宽 指服务器的高度贝尔实验室 Unix 肯汤普森 & 丹尼斯里奇二人合作用…

【ArcGIS微课1000例】0003:按属性选择(Select by Attributes)

在使用ArcGIS时,可以使用 SQL 表达式基于要素属性来选择要素。 通过按属性选择 对话框可为 SQL 表达式定义一个或多个由属性、运算符和计算构成的条件。给定图层上生成的要素选择内容满足这些条件。 文章目录 按属性选择工具1. 工具箱→按属性选择图层2. 菜单栏→按属性选择3.…

[转]Android 常见安全漏洞修复理论与实践

前言 前段时间公司对应用在爱加密上进行了安全扫描&#xff0c;本文将基于爱加密的漏洞分析报告&#xff0c;针对部分内容&#xff0c;介绍理论修复实践 最小化特权准则概念介绍 最小化特权准则&#xff0c;即指组件只能供自身应用调用&#xff0c;尽可能禁止其他应用访问及…

C语言试题158之从键盘输入一些字符,逐个把它们送到磁盘上去,直到输入一个#为止。

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目:从键盘输入一些字符,逐个把…

html5--3.2 input元素(1)

html5--3.2 input元素(1) 学习要点 input元素及其属性input元素 用来设置表单中的内容项&#xff0c;比如输入内容的文本框&#xff0c;按钮等不仅可以布置在表单中&#xff0c;也可以在表单之外的元素使用input元素的属性 type属性&#xff1a;指定输入内容的类型&#xff0c;…

css3 3D

● css3 3D旋转 ○ rotateX() 方法&#xff0c;元素围绕其 X 轴以给定的度数进行旋转 ○ rotateY() 方法&#xff0c;元素围绕其 Y 轴以给定的度数进行旋转 ○ rotateZ(angle)&#xff0c;定义沿 Z 轴的 3D 旋转。 ● 3D景深 ○ perspective(n)&#xff0c;景深&#xff0c;离屏…

我是怎么自学 Git / GitHub 的?

大家好我是鱼皮&#xff0c;Git 和 GitHub 是如今团队协作开发必不可少的技能&#xff0c;且不说程序员&#xff0c;就连很多产品也在学习它们。今天分享一下我自学 Git 和 GitHub 的经验&#xff0c;希望起到一个 导学 的作用&#xff0c;帮助大家抓住重点&#xff0c;节省时间…

[转]Android 代码混淆和加固 so库 简单教你一行代码实现

混淆 因为开启混淆会使编译时间变长&#xff0c;所以debug模式下不开启。我们需要做的是&#xff1a; 1.将release下minifyEnabled的值改为true&#xff0c;打开混淆&#xff1b; 2.buildConfigField 不显示log日志 为什么要混淆&#xff1a; 优化java的字节码减小apk文件的大…

【ArcGIS微课1000例】0004:值提取至点(Extract value to point)

文章目录 问题描述值提取至点工具介绍案例实现过程注意事项问题描述 研究区分布有成千上万个离散的矢量点(根据范围创建随机点),但是点上没有高程值,研究区DEM是有的,那么怎样在ArcGIS中提取每个点对应的高程值? 离散点分布情况: DEM数据(ArcGlobe中三维显示):

C语言试题159之计算字符串中子串出现的次数

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目:两个字符串连接程序 2 、温馨…

关于Android studio找不到sqlite数据库的解决方法

打开Android Device Monitor,剩下的与Eclipse相同。转载于:https://blog.51cto.com/10237758/1761397

linux ubuntu deepin apache2 rewrite

2019独角兽企业重金招聘Python工程师标准>>> apache php 环境装好了&#xff0c;下载了TP5的项目&#xff0c;然后部署上去之后&#xff0c;端口81&#xff0c;&#xff0c;但是 访问 127.0.0.1:81 正常 127.0.0.1:81/admin&#xff0c;报错 404 Not Found 原因是,…

论DATASNAP远程方法支持自定义对象作参数

论DATASNAP远程方法支持自定义对象作参数 DATASNAP远程方法已经可以支持自定义对象作参数&#xff0c;这是非常方便的功能。 1&#xff09;自定义对象 type TMyInfo class(TObject) public AccountNo: string; SQL: string; Params: string; end; 2&#xff09;远程方法定义 f…

[转]Android-Proguard(代码混淆)

一&#xff1a;混淆是什么&#xff0c;该怎么做&#xff1f; 如果我们的app正常发布就必须要经历混淆这一步&#xff0c;混淆可以使我们的app不那么容易被别人用反编译工具破解&#xff0c;就算被破解&#xff0c;想要读懂我们的源码也是非常费劲的&#xff0c;因为混淆过的源码…