代理模式-业务安全漏洞挖掘归纳总结-Linux文件/文件夹打包zip命令-cve-2024-53961-cve-2024-53961-jquery.serialize-分钱-分钱-nginx 测试页面配置 案例- 静态页面-图片页面-Linux的/etc/fstab文件详解-网络运营-算法思维训练(四)| 哈希表?-nginx-Docker安装Gitlab社区版-七条-震-震-业务安全漏洞挖掘归纳总结-法理-法理-业务安全漏洞挖掘归纳总结-ie7-电视频道-uid-uid-基于jQuery的输入框无值自动显示指定数据的实现代码-Linux文件/文件夹打包zip命令-jquery.ajax之beforeSend方法使用介绍-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-出血-出血-Feed-rawtherapee-mybatisplus转义模糊查询-Promethues如何监控Tomcat-vps回程一键脚本|TCP回程|ICMP回程|IPV6回程测试-xunsearch-Python 2 与 3 共存了 11 年,新年就要和它道别-某某-某某-uid-uid-WAF-css改变鼠标形状-scikit-image-Redis数据结构及常见命令-Python高手之路-nprogress-K8S 生态周报| Ingress NGINX 项目暂停接收新功能将专注于稳定性提升-电话-win10Tomcat环境配置-分钱-分钱-url传值-私有-利用HTML5的CORS特性绕过httpOnly的限制实现XSS会话劫持-在PVE中通过虚拟机安装iStoreOS路由系统与手动安装软件-借助 minikube 上手 OpenFaaS-【好玩儿的Docker项目】自建一个加密鸽(可以阅后即焚的共享笔记或文件服务)——cryptgeon-绿联Pro 安装阅读3容器,部署自己的小说阅读器-sh-xwifi-xwifi-Mysql8.0源码安装和基础配置-OpenConnect Android 使用教程-《JavaScript高级程序设计》笔记-Video Reviews on Amazon-薪酬-用 Tekton 在 Kubernetes 中编写你的第一条 CI/CD 流水线-密码防护警示-form表单-Linux文件/文件夹打包zip命令-【大屏】墨青色 | 数据监测系统设计理念(深浅两款)-iis5-iis5-multi-stage-cve-2018-2019-multi-stage-禁用appxsvc服务-Feign Client 异常处理-SVG滤镜-轻松访问 Yahoo 日文网-libpcre.so.1-operating-operating-apache+php+mysql-将代码库从 SVN 迁移至 Git 并保留所有 commit 记录-越-越-【WEB 系列】SpringBoot 集成 Mybatis-Plus-整点-webcruiser3.5.5-e_all-webcruiser3.5.5-Markdown Editor-Linux文件/文件夹打包zip命令-kubo-kubo-SSH命令问题汇总-前端研发-illustration-MybatisPlus拦截并修改SQL语句-WordPress“正在执行例行维护,请一分钟后回来“解决方法-分别-分钱-分钱-Spring Security 中的 HttpSecurity 与 WebSecurity-业务安全漏洞挖掘归纳总结-彩色-AI工具制作视频-kv-kv-欢迎使用 Typecho-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-JavaScript笔记-轻松学习jQuery插件EasyUI EasyUI创建树形菜单-enctype-linux firewalld 防火墙开放3306端口-带你了解 MyBatis 插件设计演化过程-SQLite-在Azure Functions中在运行时安装Python模块。-Android Studio添加jar或aar依赖的两种方法-Mybatis 插件实现动态设置参数-利用 Python 爬取网站的新手指南-MybatisPlus 分页查询total一直为0解决方案-React中如何使用Next.js进行服务端渲染(SSR)和静态网站生成(SSG)?-ElasticSearch-用Cloudflare(自定义域名)和Nginx搭建ChatGPT API代理,解决受限地区无法访问使用问题-linux安装宋体中文字体-vps-Lua笔记-Linux文件/文件夹打包zip命令-构建具有重叠记录的时间轴 – SQL-DB2-IBM-MySQL备份软件mydumper编译安装及使用-Jquery实现鼠标移上弹出提示框、移出消失思路及代码-sjtug-Page Camera-droidVNC NG-CatOCR易飞文字识别-Linux文件权限详解,权限600/755/644等是什么意思?-cve-2016-10033-MybatisPlus拦截并修改SQL语句-捷-捷-相片处理软件-源于-js实现图片放大缩小功能后进行复杂排序的方法-使用jquery提交form表单并自定义action的方法-Spring Boot 在运行时启用和禁用端点-业务安全漏洞挖掘归纳总结-Docker Hub上镜像发现挖矿蠕虫病毒,已导致2000台主机感染-urls-springbean-全不-RTF Viewer-Linux文件/文件夹打包zip命令-directory-Linux文件/文件夹打包zip命令-不存在-视频换脸-cve-2023-21768-cve-2023-21768-CVE-2018-4990 Adobe Reader代码执行漏洞利用分析-1000u-回来-回来-好消息,Kimi大模型可以接入微信了!-无法在带有Typescript的Next.js项目中运行Cypress open命令。-webcruiser3.5.5-webcruiser3.5.5-nginx+fancy-expecting-python3.6.8-python3.6.8-1.7-1.7-DynamoDB系列之--几个核心的概念-openfaas-openfaas-Linux升级Docker后重启容器出现错误Unknown runtime specified docker-runc-华为交换机VTY用户界面属性配置教程-区别-ngxtop-ngxtop-firebug-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-php7安装tidy扩展-直接-clickonce-cve-2018-2019-cve-2018-2019-recursion-仪表盘构建-尚-mappress-尚-mappress-钉-foo-FINX-linux|安装|使用|netcat|完善-开搞-开搞-jquery导航制件jquery鼠标经过变色效果示例-优秀-Spring Boot 中 @ComponentScan 与 @EnableAutoConfiguration 的区别-搭-离谱,这个 AI 穿搭造型师每年狂赚 300 万美元!-Stackup-fragment-jQuery实现图片走马灯效果的原理分析-将被-谷歌-【折腾笔记】利用“双不限”流量卡跑PCDN-店小秘助手-ngxtop-Android:自定义对话框-ngxtop-H3C-Linux搭建RabbitMQ集群-业务安全漏洞挖掘归纳总结-不充分-不充分-心脏出血漏洞利用工具-javascript异步编程之generator(生成器函数)与asnyc/await语法糖-云服务器-mlog_checkpoint-AUTOPRUNE-数据库安装-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-線上會議自動接受工具-业务安全漏洞挖掘归纳总结-kv-kv-dd-idea插件 kafka-Windows 11:最新更新带来一波新功能-WebAssembly和Docker到底有什么关系?-ChatGPT-olm-JavaScript的异步编程之Promise-哈希(Hash)算法-Reservoir Sampling 蓄水池采样算法-软件教程-parrot linux 安装谷歌浏览器-es-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-000-tplink-tplink-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-Linux文件/文件夹打包zip命令-准备就绪-法理-法理-拷贝到-Nginx虚拟主机配置-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-notepad++-notepad++-Java 设计模式之观察者模式(十六)-Github-JQuery中使用.each()遍历元素学习笔记-日常运维-pod-php关于精准计算的模块 BCMath-K8S 生态周报| Kubernetes Ingress-NGINX 功能冻结前最后一个版本发布-Mysql-Zabbix Proxy升级完成后提示MySQL字符集不符合要求-AI换脸本地一键整合包:Facefusion 2.6.1无需部署 一键启动!-拷贝-什么是CDN-CentOS 命令的方式添加firewall端口-geotrust-zabbix 修改 告警阈值为90%-“来此加密”:轻松在线申请多域名和泛域名SSL证书-吊打Coze:原生Kimi接入个人微信,免费接入,打包下载解压即用-多少年-多少年-xwifi-xwifi-Save image to Downloads-WordPress添加QQ、新浪微博第三方登录功能-VSCode Remote SSH: Bad Owner or Permissions-溯源-mappress-Linux文件/文件夹打包zip命令-CSS Color Names-mdadm-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-Linux文件/文件夹打包zip命令-html中实现文字滚动的两种方式-资源池对象-tools-git笔记-EasyGo-系统漏洞-系统漏洞-Docker常用命令-JQuery拖动表头边框线调整表格列宽效果代码-Clash -看我如何利用漏洞窃取麦当劳网站注册用户密码-类似于-pf4j-got-JDK国内镜像加速下载,免登录!-Python机器学习——随机森林-Malta Stock Stalker-签为-使用reigistry对Docker镜像加速下载-Linux下配置DNS服务器完全文档-业务安全漏洞挖掘归纳总结-Easyv-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-10 款绚丽的前端 CSS 菜单导航动画 + 打包源码下载-Django CRUD操作-Linux文件/文件夹打包zip命令-prisma-不充分-不充分-在 Kubernetes 上使用 Flask 搭建 Python 微服务-Centos7 _audit.so: undefined symbol: audit_can_read故障处理-任意两个点的曲线连接JS算法-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-IntelliJ IDEA常用快捷键-WordPress免费响应式主题Ality0.33版-ab-在React中,使用`useRef` 声明式地添加项目还是使用`state`更具性能优势?-prometheus+grafana+alertmanager+-image-rendering-native-metrics-native-metrics-jQuery Tab插件 用于在Tab中显示iframe,附源码和详细说明-掉线-接活儿利器-Elasticsearch 7.9.1集群安装配置-esxi6.7_cve-2018-3646-大神-软件教程-ngxtop-ngxtop- Eslint-Plugin-Vue -可更新-jquery表单验证框架提供的身份证验证方法(示例代码)-jquery实现的元素的left增加N像素 鼠标移开会慢慢的移动到原来的位置-webcruiser3.5.5-webcruiser3.5.5-备选-rider-Amazing Auto Refresh-数学原理-dmm-dmm-java全局变量,java全局变量怎么定义-新视野-指令重排序、内存屏障很难?看完这篇你就懂了!-消费者-lifecycle-滑入-PochtaPlugin Adapter-把代码一键生成图片在线工具,支持JAVA、PHP等语言-双亲-linux-开源软件-jQuery 动态云标签插件-WordPress站点添加评论输入特效-clause-Linux部署Prometheus+Alertmanager并配置邮件告警-掌握强大的 Git 变基命令-软件使用-jquery.icolor.js-日常运维-组合-Twitter account detector-Linux文件/文件夹打包zip命令-iptables 及 docker 容器网络分析-iOS 更新会耗尽 iPhone 的电池吗?答案:并不那么明显-code-breaking-JavaScript优化方向和策略-Python一个键对应多个值-2024年投资Aleo算力服务器,有可能实现财富自由?-关于Robots.txt和SEO优化:它们之间有什么过往交集?-poscms-native-metrics-越-poscms-native-metrics-越-高龄-高龄-开源工具-operating-operating-Popper Stopper Pro-业务安全漏洞挖掘归纳总结-Linux文件/文件夹打包zip命令-posters-日常运维-手环-column-JQuery对ASP.NET MVC数据进行更新删除-cve-2024-56334-cve-2024-56334-wsappx-Linux添加新硬盘后,完美分区详细图解!-Linux Epoll IO 模型-操作系统-VS Code 报告 PHP 中从父类继承的方法出现假阳性。-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-ARMv8-cudnn-经验分享-Linux文件/文件夹打包zip命令-阅读代码-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-什么是L1和L2?区块链中的L1和L2有什么区别?-Rust中的闭包与函数-AI语音克隆-软件教程-python实现并发请求-信息管理-使用JavaScript的不可变数组方法编写更干净的代码-text4-win11家庭版升级为企业版开启NFS功能-暴雪-盒盖-cve-2019-0708-bluekeep-cve-2019-0708-bluekeep-Timr-渠道-Redis 哈希(Hash)-软件使用-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-看过来-新版 Spring Security 中的路径匹配机制-ElasticSearch-最新炸裂的五款ai换脸工具,收藏~-取-inline-size-Radioplayer UK-Your Arbor - Sustainable Shopping Assistant-J Dial Scraper-radmin-radmin-使用Spring框架的优点-打上-打上-模板的优化-Cantonese Popup Dictionary-xwifi-xwifi-Firefox-Docker使用pg_restore 出现Segmentation fault (core dumped)-攻击-师-paddle2onnx-日常运维-Python MetaClass-git其它-通过Python脚本获取指定日期一周范围时间-看到“游戏开发大神毛星云离世”的消息后,作为Web前端开发或后台程序员的我们需要思考些什么?-广播-cve-2024-56334-submodule-SQL语句的种类和代表命令(DDL DCL DML)-Wireshark软件识别解析 Portal 报文(默认抓取了portal报文,并不是说没有抓取,只是不解析而已)(附下载地址)-参考-工具盒子" /> 代理模式-业务安全漏洞挖掘归纳总结-Linux文件/文件夹打包zip命令-cve-2024-53961-cve-2024-53961-jquery.serialize-分钱-分钱-nginx 测试页面配置 案例- 静态页面-图片页面-Linux的/etc/fstab文件详解-网络运营-算法思维训练(四)| 哈希表?-nginx-Docker安装Gitlab社区版-七条-震-震-业务安全漏洞挖掘归纳总结-法理-法理-业务安全漏洞挖掘归纳总结-ie7-电视频道-uid-uid-基于jQuery的输入框无值自动显示指定数据的实现代码-Linux文件/文件夹打包zip命令-jquery.ajax之beforeSend方法使用介绍-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-出血-出血-Feed-rawtherapee-mybatisplus转义模糊查询-Promethues如何监控Tomcat-vps回程一键脚本|TCP回程|ICMP回程|IPV6回程测试-xunsearch-Python 2 与 3 共存了 11 年,新年就要和它道别-某某-某某-uid-uid-WAF-css改变鼠标形状-scikit-image-Redis数据结构及常见命令-Python高手之路-nprogress-K8S 生态周报| Ingress NGINX 项目暂停接收新功能将专注于稳定性提升-电话-win10Tomcat环境配置-分钱-分钱-url传值-私有-利用HTML5的CORS特性绕过httpOnly的限制实现XSS会话劫持-在PVE中通过虚拟机安装iStoreOS路由系统与手动安装软件-借助 minikube 上手 OpenFaaS-【好玩儿的Docker项目】自建一个加密鸽(可以阅后即焚的共享笔记或文件服务)——cryptgeon-绿联Pro 安装阅读3容器,部署自己的小说阅读器-sh-xwifi-xwifi-Mysql8.0源码安装和基础配置-OpenConnect Android 使用教程-《JavaScript高级程序设计》笔记-Video Reviews on Amazon-薪酬-用 Tekton 在 Kubernetes 中编写你的第一条 CI/CD 流水线-密码防护警示-form表单-Linux文件/文件夹打包zip命令-【大屏】墨青色 | 数据监测系统设计理念(深浅两款)-iis5-iis5-multi-stage-cve-2018-2019-multi-stage-禁用appxsvc服务-Feign Client 异常处理-SVG滤镜-轻松访问 Yahoo 日文网-libpcre.so.1-operating-operating-apache+php+mysql-将代码库从 SVN 迁移至 Git 并保留所有 commit 记录-越-越-【WEB 系列】SpringBoot 集成 Mybatis-Plus-整点-webcruiser3.5.5-e_all-webcruiser3.5.5-Markdown Editor-Linux文件/文件夹打包zip命令-kubo-kubo-SSH命令问题汇总-前端研发-illustration-MybatisPlus拦截并修改SQL语句-WordPress“正在执行例行维护,请一分钟后回来“解决方法-分别-分钱-分钱-Spring Security 中的 HttpSecurity 与 WebSecurity-业务安全漏洞挖掘归纳总结-彩色-AI工具制作视频-kv-kv-欢迎使用 Typecho-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-JavaScript笔记-轻松学习jQuery插件EasyUI EasyUI创建树形菜单-enctype-linux firewalld 防火墙开放3306端口-带你了解 MyBatis 插件设计演化过程-SQLite-在Azure Functions中在运行时安装Python模块。-Android Studio添加jar或aar依赖的两种方法-Mybatis 插件实现动态设置参数-利用 Python 爬取网站的新手指南-MybatisPlus 分页查询total一直为0解决方案-React中如何使用Next.js进行服务端渲染(SSR)和静态网站生成(SSG)?-ElasticSearch-用Cloudflare(自定义域名)和Nginx搭建ChatGPT API代理,解决受限地区无法访问使用问题-linux安装宋体中文字体-vps-Lua笔记-Linux文件/文件夹打包zip命令-构建具有重叠记录的时间轴 – SQL-DB2-IBM-MySQL备份软件mydumper编译安装及使用-Jquery实现鼠标移上弹出提示框、移出消失思路及代码-sjtug-Page Camera-droidVNC NG-CatOCR易飞文字识别-Linux文件权限详解,权限600/755/644等是什么意思?-cve-2016-10033-MybatisPlus拦截并修改SQL语句-捷-捷-相片处理软件-源于-js实现图片放大缩小功能后进行复杂排序的方法-使用jquery提交form表单并自定义action的方法-Spring Boot 在运行时启用和禁用端点-业务安全漏洞挖掘归纳总结-Docker Hub上镜像发现挖矿蠕虫病毒,已导致2000台主机感染-urls-springbean-全不-RTF Viewer-Linux文件/文件夹打包zip命令-directory-Linux文件/文件夹打包zip命令-不存在-视频换脸-cve-2023-21768-cve-2023-21768-CVE-2018-4990 Adobe Reader代码执行漏洞利用分析-1000u-回来-回来-好消息,Kimi大模型可以接入微信了!-无法在带有Typescript的Next.js项目中运行Cypress open命令。-webcruiser3.5.5-webcruiser3.5.5-nginx+fancy-expecting-python3.6.8-python3.6.8-1.7-1.7-DynamoDB系列之--几个核心的概念-openfaas-openfaas-Linux升级Docker后重启容器出现错误Unknown runtime specified docker-runc-华为交换机VTY用户界面属性配置教程-区别-ngxtop-ngxtop-firebug-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-php7安装tidy扩展-直接-clickonce-cve-2018-2019-cve-2018-2019-recursion-仪表盘构建-尚-mappress-尚-mappress-钉-foo-FINX-linux|安装|使用|netcat|完善-开搞-开搞-jquery导航制件jquery鼠标经过变色效果示例-优秀-Spring Boot 中 @ComponentScan 与 @EnableAutoConfiguration 的区别-搭-离谱,这个 AI 穿搭造型师每年狂赚 300 万美元!-Stackup-fragment-jQuery实现图片走马灯效果的原理分析-将被-谷歌-【折腾笔记】利用“双不限”流量卡跑PCDN-店小秘助手-ngxtop-Android:自定义对话框-ngxtop-H3C-Linux搭建RabbitMQ集群-业务安全漏洞挖掘归纳总结-不充分-不充分-心脏出血漏洞利用工具-javascript异步编程之generator(生成器函数)与asnyc/await语法糖-云服务器-mlog_checkpoint-AUTOPRUNE-数据库安装-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-線上會議自動接受工具-业务安全漏洞挖掘归纳总结-kv-kv-dd-idea插件 kafka-Windows 11:最新更新带来一波新功能-WebAssembly和Docker到底有什么关系?-ChatGPT-olm-JavaScript的异步编程之Promise-哈希(Hash)算法-Reservoir Sampling 蓄水池采样算法-软件教程-parrot linux 安装谷歌浏览器-es-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-000-tplink-tplink-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-Linux文件/文件夹打包zip命令-准备就绪-法理-法理-拷贝到-Nginx虚拟主机配置-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-notepad++-notepad++-Java 设计模式之观察者模式(十六)-Github-JQuery中使用.each()遍历元素学习笔记-日常运维-pod-php关于精准计算的模块 BCMath-K8S 生态周报| Kubernetes Ingress-NGINX 功能冻结前最后一个版本发布-Mysql-Zabbix Proxy升级完成后提示MySQL字符集不符合要求-AI换脸本地一键整合包:Facefusion 2.6.1无需部署 一键启动!-拷贝-什么是CDN-CentOS 命令的方式添加firewall端口-geotrust-zabbix 修改 告警阈值为90%-“来此加密”:轻松在线申请多域名和泛域名SSL证书-吊打Coze:原生Kimi接入个人微信,免费接入,打包下载解压即用-多少年-多少年-xwifi-xwifi-Save image to Downloads-WordPress添加QQ、新浪微博第三方登录功能-VSCode Remote SSH: Bad Owner or Permissions-溯源-mappress-Linux文件/文件夹打包zip命令-CSS Color Names-mdadm-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-Linux文件/文件夹打包zip命令-html中实现文字滚动的两种方式-资源池对象-tools-git笔记-EasyGo-系统漏洞-系统漏洞-Docker常用命令-JQuery拖动表头边框线调整表格列宽效果代码-Clash -看我如何利用漏洞窃取麦当劳网站注册用户密码-类似于-pf4j-got-JDK国内镜像加速下载,免登录!-Python机器学习——随机森林-Malta Stock Stalker-签为-使用reigistry对Docker镜像加速下载-Linux下配置DNS服务器完全文档-业务安全漏洞挖掘归纳总结-Easyv-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-10 款绚丽的前端 CSS 菜单导航动画 + 打包源码下载-Django CRUD操作-Linux文件/文件夹打包zip命令-prisma-不充分-不充分-在 Kubernetes 上使用 Flask 搭建 Python 微服务-Centos7 _audit.so: undefined symbol: audit_can_read故障处理-任意两个点的曲线连接JS算法-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-IntelliJ IDEA常用快捷键-WordPress免费响应式主题Ality0.33版-ab-在React中,使用`useRef` 声明式地添加项目还是使用`state`更具性能优势?-prometheus+grafana+alertmanager+-image-rendering-native-metrics-native-metrics-jQuery Tab插件 用于在Tab中显示iframe,附源码和详细说明-掉线-接活儿利器-Elasticsearch 7.9.1集群安装配置-esxi6.7_cve-2018-3646-大神-软件教程-ngxtop-ngxtop- Eslint-Plugin-Vue -可更新-jquery表单验证框架提供的身份证验证方法(示例代码)-jquery实现的元素的left增加N像素 鼠标移开会慢慢的移动到原来的位置-webcruiser3.5.5-webcruiser3.5.5-备选-rider-Amazing Auto Refresh-数学原理-dmm-dmm-java全局变量,java全局变量怎么定义-新视野-指令重排序、内存屏障很难?看完这篇你就懂了!-消费者-lifecycle-滑入-PochtaPlugin Adapter-把代码一键生成图片在线工具,支持JAVA、PHP等语言-双亲-linux-开源软件-jQuery 动态云标签插件-WordPress站点添加评论输入特效-clause-Linux部署Prometheus+Alertmanager并配置邮件告警-掌握强大的 Git 变基命令-软件使用-jquery.icolor.js-日常运维-组合-Twitter account detector-Linux文件/文件夹打包zip命令-iptables 及 docker 容器网络分析-iOS 更新会耗尽 iPhone 的电池吗?答案:并不那么明显-code-breaking-JavaScript优化方向和策略-Python一个键对应多个值-2024年投资Aleo算力服务器,有可能实现财富自由?-关于Robots.txt和SEO优化:它们之间有什么过往交集?-poscms-native-metrics-越-poscms-native-metrics-越-高龄-高龄-开源工具-operating-operating-Popper Stopper Pro-业务安全漏洞挖掘归纳总结-Linux文件/文件夹打包zip命令-posters-日常运维-手环-column-JQuery对ASP.NET MVC数据进行更新删除-cve-2024-56334-cve-2024-56334-wsappx-Linux添加新硬盘后,完美分区详细图解!-Linux Epoll IO 模型-操作系统-VS Code 报告 PHP 中从父类继承的方法出现假阳性。-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-ARMv8-cudnn-经验分享-Linux文件/文件夹打包zip命令-阅读代码-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-什么是L1和L2?区块链中的L1和L2有什么区别?-Rust中的闭包与函数-AI语音克隆-软件教程-python实现并发请求-信息管理-使用JavaScript的不可变数组方法编写更干净的代码-text4-win11家庭版升级为企业版开启NFS功能-暴雪-盒盖-cve-2019-0708-bluekeep-cve-2019-0708-bluekeep-Timr-渠道-Redis 哈希(Hash)-软件使用-Kubernetes部署Prometheus+Grafana+Alertmanager+NFS并配置邮件报警-看过来-新版 Spring Security 中的路径匹配机制-ElasticSearch-最新炸裂的五款ai换脸工具,收藏~-取-inline-size-Radioplayer UK-Your Arbor - Sustainable Shopping Assistant-J Dial Scraper-radmin-radmin-使用Spring框架的优点-打上-打上-模板的优化-Cantonese Popup Dictionary-xwifi-xwifi-Firefox-Docker使用pg_restore 出现Segmentation fault (core dumped)-攻击-师-paddle2onnx-日常运维-Python MetaClass-git其它-通过Python脚本获取指定日期一周范围时间-看到“游戏开发大神毛星云离世”的消息后,作为Web前端开发或后台程序员的我们需要思考些什么?-广播-cve-2024-56334-submodule-SQL语句的种类和代表命令(DDL DCL DML)-Wireshark软件识别解析 Portal 报文(默认抓取了portal报文,并不是说没有抓取,只是不解析而已)(附下载地址)-参考-工具盒子" />

51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Java 设计模式之装饰模式(八)

一、前言 {#一、前言}

本篇主题为结构型模式中的第三个模式--装饰模式。上篇 Java 设计模式主题为 《Java 设计模式之桥接模式(七)》

二、简单介绍 {#二、简单介绍}

2.1 定义 {#2.1-定义}

装饰(Decorator)模式又叫做包装模式,其功能是动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活,是继承关系的一个替换方案。

2.2 参与角色 {#2.2-参与角色}

  1. Component:定义一个对象接口,可以给这些对象动态地添加职责。

  2. ConcreteComponent:定义一个对象,可以给这个对象添加一些职责。

  3. Decorator:维持一个指向 Component 对象的指针,并定义一个与 Component 接口一致的接口。

  4. ConcreteDecorator:向组件添加职责。

2.3 应用场景 {#2.3-应用场景}

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

  2. 当不能采用生成子类的方法进行扩充时。

三、实现方式 {#三、实现方式}

我们以人的打扮为例。人打扮需要穿衣,穿裤,穿鞋子。代码表示如下:

Person 类:

|------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public class Person { private String name; public Person(String name) { this.name = name; } public void putOnClothes() { System.out.println(this.name + "穿衣服"); } public void putOnTrousers() { System.out.println(this.name + "穿裤子"); } public void putOnShoes() { System.out.println(this.name + "穿鞋子"); } } |

客户端:

|---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 | public class Client { public static void main(String[] args) { Person person = new Person("小白"); person.putOnClothes(); person.putOnTrousers(); person.putOnShoes(); } } |

打印:

|---------------|---------------------------| | 1 2 3 | 小白穿衣服 小白穿裤子 小白穿鞋子 |

上述代码很简单,但是扩展性不好。当我们需要添加打领带、戴手表的行为时,需要修改 Person 类,违背了开放封闭原则。

因此,我们需要将人和打扮的行为抽离出来:

Person 类:

|---------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 | public class Person { private String name; public Person(String name) { this.name = name; } public String getName() { return name; } } |

打扮类:

|------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | public abstract class DressUp { public abstract void dressup(Person person); } class ClothesDressUp extends DressUp { @Override public void dressup(Person person) { System.out.println(person.getName() + "穿衣服"); } } class TrousersDressUp extends DressUp { @Override public void dressup(Person person) { System.out.println(person.getName() + "穿裤子"); } } class ShoesDressUp extends DressUp { @Override public void dressup(Person person) { System.out.println(person.getName() + "穿鞋子"); } } |

客户端:

|---------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class Client { public static void main(String[] args) { Person person = new Person("小白"); DressUp du1 = new ClothesDressUp(); du1.dressup(person); DressUp du2 = new TrousersDressUp(); du2.dressup(person); DressUp du3 = new ShoesDressUp(); du3.dressup(person); } } |

执行结果与上文的一致。现在,当我们添加新的打扮行为时,只需新增 DressUp 的子类即可。

但是,上边的代码没有封装性,每打扮一次都要调用 dressup 方法一次,就感觉人是光着身在公共场合进行打扮穿衣、穿鞋。因此,我们需要一种模式将这些打扮的细节封装起来,就像建造者模式一样。

不过,此次的需求不能使用建造者模式。因为建造者模式封装过程/细节是一个固定的顺序/模式,而当前需求是人的打扮,打扮的行为是多种多样的,如:穿衣穿裤、穿衣打领带、穿鞋戴手表等。

这样就引出了本章的主题--装饰模式:

Person 接口与实现类(Component 和 ConcreteComponent):

|---------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 | public interface Person { public void decorate(); } class Man implements Person { @Override public void decorate() { System.out.println("男人打扮"); } } |

装饰类(Decorator 和 ConcreteDecorator):

|------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | public class Decorator implements Person { private Person person; public Decorator(Person person) { this.person = person; } @Override public void decorate() { this.person.decorate(); } } class ClothesDecorator extends Decorator { public ClothesDecorator(Person person) { super(person); } public void decorate() { super.decorate(); System.out.println("穿衣服"); } } class TrousersDecorator extends Decorator { public TrousersDecorator(Person person) { super(person); } public void decorate() { super.decorate(); System.out.println("穿裤子"); } } class ShoesDecorator extends Decorator { public ShoesDecorator(Person person) { super(person); } public void decorate() { super.decorate(); System.out.println("穿鞋子"); } } |

客户端:

|---------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public class Client { public static void main(String[] args) { Person person = new Man(); Person decorator = new Decorator(person); System.out.println("======第一种打扮======="); ClothesDecorator cd = new ClothesDecorator(decorator); TrousersDecorator td = new TrousersDecorator(cd); td.decorate(); System.out.println("======第二种打扮======="); ShoesDecorator sd = new ShoesDecorator(person); sd.decorate(); } } |

打印:

|-----------------------|---------------------------------------------------------------------| | 1 2 3 4 5 6 7 | ======第一种打扮======= 男人打扮 穿衣服 穿裤子 ======第二种打扮======= 男人打扮 穿鞋子 |

总结:装饰模式有效地把类的核心职责和装饰功能区分开来,而且去除了相关类的重复的装饰逻辑。

UML 类图表示如下:

赞(0)
未经允许不得转载:工具盒子 » Java 设计模式之装饰模式(八)