BCSP-玄子Share-Java框基础_工厂模式/代理模式
三、设计模式
3.1 设计模式简介
- 软件设计中的
三十六计 - 是人们在长期的软件开发中的经验总结
- 是对某些特定问题的经过实践检验的特定解决方法
- 被广泛运用在 Java 框架技术中
3.1.1 设计模式的优点
- 设计模式是可复用的面向对象软件的基础
- 可以更加简单方便地复用成功的设计和体系结构
- 帮助开发者做出有利于系统复用的选择,避免损害系统复用性的设计
- 使其他开发者更加容易理解其设计思路,便于团队交流
3.1.2 设计模式分类
GoF(Gang of Four,四人组)设计模式分为23种
| 范围/目的 | 创建型模式 | 结构型模式 | 行为型模式 |
|---|---|---|---|
| 类模式 | 工厂方法 | (类)适配器 | 模板方法解释器 |
| 对象模式 | 单例 原型 抽象工厂 建造者 | 代理 (对象)适配器 桥接 装饰 外观 享元 组合 | 策略 命令 职责链 状态 观察者 中介者 迭代器 访问者 备忘录 |
3.1.3 面向对象设计原则
单一职责原则
- 一个类应该有且仅有一个引起它变化的原因
- 一个类应该只负责一个职责
开闭原则
- 对扩展开放,对修改关闭
里氏替换原则
- 引用基类的地方必须能透明地使用其子类的对象
- 可以用来判断继承关系是否合理
依赖倒置原则
- 依赖于抽象而不依赖于具体实现,针对接口编程
接口隔离原则
- 尽量将庞大臃肿的接口拆分成更小更具体的接口
- 接口中只包含客户感兴趣的方法
迪米特法则
- 又称最少知道原则
- 一个软件实体应当尽可能少地与其他实体发生相互作用
合成复用原则
- 尽量使用组合/聚合的方式而不是继承关系达到软件复用的目的
- 是 has-a 关系
3.2 简单工厂模式
如何解决类似“Service与某个具体Dao实现”耦合的问题?
将创建工作转移出来避免在Service中创建具体的Dao实现类,产生耦合
简单工厂模式,又叫做静态工厂方法模式,不属于 GoF 的23种设计模式之一,可以理解为工厂模式的一个特殊实现
3.2.1 简单工厂模式+依赖倒置原则
依据依赖倒置原则,使用setter方法传递依赖关系,减少Service对工厂类的依赖,降低耦合
public class NewsServiceImpl implements NewsService {private NewsDao dao;public void setDao(NewsDao dao) {this.dao = dao;}… …
}
3.2.2 简单工厂+参数
简单工厂模式可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类
// 创建NewsDao实例的工厂方法
public static NewsDao getInstance(String key) {switch (key) {case "mysql":return new NewsDaoMySqlImpl();case "oracle":return new NewsDaoOracleImpl();case "redis":return new NewsDaoRedisImpl();default:throw new RuntimeException("无效的数据库类型:" + key + " ,DAO获取失败");}
}
要创建的产品不多且逻辑不复杂的情况,可以考虑简单工厂模式
简单工厂模式包含如下角色
- 工厂(Factory)
- 抽象产品(Product)
- 具体产品(Concrete Product)
增加新的产品需要修改,工厂方法的判断逻辑,不符合开闭原则
3.3 工厂方法模式
3.3.1 实现方式
对简单工厂模式的进一步抽象,工厂方法模式的主要角色如下
- 抽象产品(Product)
- 抽象工厂(Abstract Factory)
- 具体产品(Concrete Product)
- 具体工厂(Concrete Factory)
3.3.2 代码案例
创建抽象工厂接口
public interface AbstractFactory {public NewsDao getInstance();
}
为不同NewsDao实现创建相对应的具体工厂
// 以生产NewsDaoMySqlImpl实例的工厂为例
public class MySqlDaoFactory implements AbstractFactory {@Overridepublic NewsDao getInstance() {return new NewsDaoMySqlImpl();}
}
在测试方法中通过特定工厂生产相关的NewsDao实例
AbstractFactory factory = new MySqlDaoFactory();
// 改变具体工厂可创建不同产品
NewsDao dao = factory.getInstance();
3.3.3 优缺点
优点
- 只需要知道具体工厂就可得到所要的产品,无须知道产品的具体创建过程
- 基于多态,便于对复杂逻辑进行封装管理
- 增加新的产品时无须对原工厂进行任何修改,满足开闭原则
缺点
- 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度
3.4 代理设计模式
单一职责原则的体现,包含如下角色
- 抽象主题(Subject)
- 真实主题(Real Subject)
- 代理(Proxy)
实现方式总体上分为静态代理和动态代理
- 静态代理由开发者针对抽象主题编写相关的代理类实现,编译之后生成代理类的class文件
- 动态代理是在运行时动态生成的,在运行时动态生成代理类字节码
3.4.1 基于接口的静态代理实现
// 抽象主题接口 - 图片
public interface Image {void display();
}// 真实主题类 - 真实图片
public class RealImage implements Image {private String filename;public RealImage(String filename) {this.filename = filename;loadImageFromDisk();}private void loadImageFromDisk() {System.out.println("Loading image from disk: " + filename);}public void display() {System.out.println("Displaying image: " + filename);}
}// 代理类 - 图片代理
public class ImageProxy implements Image {private RealImage realImage;private String filename;public ImageProxy(String filename) {this.filename = filename;}public void display() {if (realImage == null) {realImage = new RealImage(filename);}realImage.display();}
}// 调用代码
public class Client {public static void main(String[] args) {// 创建代理对象并显示图片Image image = new ImageProxy("example.jpg");image.display();}
}

3.4.2 代理模式优点分析
- 代理模式将客户与目标对象分离,在一定程度上降低了系统的耦合度
- 代理对象可以对目标对象的功能进行扩展,目标对象和扩展功能职责清晰且不会产生耦合
3.4.3 动态代理
静态代理需要手工编写代理类,存在以下弊端
- 目标对象API发生变化,代理类也必须进行修改,增加工作量且不符合开闭原则
- 通过继承得到的代理类只能对一种类型进行代理,组件较多时,代理类的开发工作量巨大
- 动态代理提供了运行时动态扩展对象行为的能力
- 能够依据给定的业务规则,在运行时动态生成代理类
3.4.4 JDK 动态代理
从JDK 1.3版本开始引入
是面向接口的代理实现
- 要求被代理的目标对象必须通过抽象主题接口进行定义
核心API
- java.lang.reflect.InvocationHandler接口
- 代理方法的调用处理程序,负责为代理方法提供业务逻辑
- 包含方法:Object invoke(Object proxy, Method method, Object[] args)
- java.lang.reflect.Proxy类
- 负责动态创建代理类及其实例
- 主要方法:static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
3.4.5 CGLIB 动态代理
如果被代理的目标对象不是通过接口进行定义的,JDK 动态代理将无法实施
- CGLIB(Code Generation Library)是一个功能强大,高性能的代码生成库
- 可以为没有实现接口的类提供代理,原理是为需要代理的类动态生成一个子类作为其代理类
需要使用继承和重写机制,CGLIB动态代理对于final类或final方法无能为力
从cglib https://github.com/cglib/cglib/releases下载所需的 jar 文件
- cglib-nodep-x.x.x.jar
主要 API
- net.sf.cglib.proxy.MethodInterceptor 接口
- 负责拦截父类的方法调用,以便加入代理的业务逻辑
- 包含方法
- Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
- net.sf.cglib.proxy.Enhancer 类
- 负责动态创建代理类及其实例
- 主要方法
- setSupperclass()
- setCallback()
- set…
- create()
3.4.6 JDK 和 CGLIB 动态代理的对比
- JDK 动态代理面向接口代理,只能对基于接口设计的目标对象进行代理
- CGLIB 动态代理可以通过继承方式实现,不依赖接口,但是不能代理 final 的类和方法
相关文章:
BCSP-玄子Share-Java框基础_工厂模式/代理模式
三、设计模式 3.1 设计模式简介 软件设计中的三十六计是人们在长期的软件开发中的经验总结是对某些特定问题的经过实践检验的特定解决方法被广泛运用在 Java 框架技术中 3.1.1 设计模式的优点 设计模式是可复用的面向对象软件的基础可以更加简单方便地复用成功的设计和体系…...
【数据结构】2015统考真题 6
题目描述 【2015统考真题】求下面的带权图的最小(代价)生成树时,可能是Kruskal算法第2次选中但不是Prim算法(从v4开始)第2次选中的边是(C) A. (V1, V3) B. (V1, V4) C. (V2, V3) D. (V3, V4) …...
HTML <track> 标签
实例 播放带有字幕的视频: <video width="320" height="240" controls="controls"><source src="forrest_gump.mp4" type="video/mp4" /><source src="forrest_gump.ogg" type="video/ogg…...
php中识别url被篡改并阻止访问的实现方式是什么
在 PHP 中,可以通过多种方式来识别并阻止 URL 被篡改的访问。以下是一些常见的方法: 基本身份验证:使用 PHP 的 $_SERVER[PHP_AUTH_USER] 和 $_SERVER[PHP_AUTH_PW] 变量可以实施基本的 HTTP 身份验证。在访问受保护的页面之前,可…...
c++ 学习 之 const,constexpr,volatile
前言 const、constexpr 和 volatile 是 C 中用于修饰变量和类型的关键字 正文 它们分别用于不同的用途: const(常量): const 用于声明常量,表示变量的值不能被修改。 它可以应用于变量、指针、引用、成员函数以及类…...
【Flink】关于jvm元空间溢出,mysql binlog冲突的问题解决
问题一:7张表是同一个mysql中的,我们进行增量同步时分别用不同的flink任务读取,造成mysql server-id冲突问题,如下: Caused by: io.debezium.DebeziumException: A slave with the same server_uuid/server_id as this…...
C#常用多线程(线程同步,事件触发,信号量,互斥锁,共享内存,消息队列)
using System; using System.Threading; using System.Windows.Forms; using UtilForm.Util;namespace UtilForm {// 线程同步,事件触发,信号量,互斥锁,共享内存,消息队列public partial class frmUIThread : Form{ Sy…...
OpenWrt系统开发笔记
openWrt英文官网: https://openwrt.org/ 中文官网: http://www.openwrt.org.cn/ 一、开发环境及编译 在github上有两个源码使用的比较多 一个是lede,地址为:https://github.com/coolsnowwolf/lede 另一个为OpenWrt的官方源码&#…...
实战 - Restful APi 格式规范
文章目录 1. 特征2. 优点3. 动作1. GET 获取资源2. POST 创建资源3. PUT 整体替换4. PATCH 部分替换5. DELETE 删除资源 4. 示例 RESTful是一种API的设计风格,他和GraphQL ,JSON-RPC,WebService类似,用于定义在CS、BS架构下暴露服…...
《Linux从练气到飞升》No.21 Linux简单实现一个shell
🕺作者: 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 😘欢迎关注:👍点赞🙌收藏✍️留言 🏇码字不易,你的👍点赞🙌收藏❤️关注对我真的…...
【iVX】iVX的低代码未来发展趋势:加速应用开发的创新之路
简介: 随着数字化转型的飞速发展,企业和组织对快速开发和交付高质量应用的需求越来越迫切。低代码开发平台作为一种创新的解决方案,极大地简化了应用程序的开发过程。在这一领域,iVX低代码平台作为领先的创业公司,正在…...
zookee 安装
1、下载安装包 weget https://downloads.apache.org/zookeeper/zookeeper-3.6.3/apache-zookeeper-3.6.3-bin.tar.gz 方案1:wget是一个下载指令,后面可以跟下载连接去从服务器上下载东西。 方案2:也可以先下载到windows上,再通…...
OpenWrt编译自己的应用程序
编译OpenWrt的应用程序可以参考OpenWrt内部其他应用程序的例程,来编写成自己的应用程序 一、OpenWrt源代码获取与编译 1.1、搭建环境 下载OpenWrt的官方源码: git clone https://github.com/openwrt/openwrt.git1.2、安装编译依赖项 sudo apt update…...
MySQL 50 题。
MySQL 50 题。 文章目录 MySQL 50 题。数据库。sql。 数据库。 CREATE SCHEMA new_schema DEFAULT CHARACTER SET utf8mb4 ;Operation failed: There was an error while applying the SQL script to the database. Executing: CREATE SCHEMA new_schema DEFAULT CHARACTER SE…...
强化学习算法总结 (1)
强化学习算法总结 (1) 1.综述 强化学习是通过与环境进行交互,来实现目标的一种计算方法。 s − a 1 − r − s ′ s - a_1 - r- s s−a1−r−s′ 1.1强化学习优化目标 p o l i c y a r g m a x p o l i c y E ( a , s ) [ r e w a r d ( s , a ) ] policy ar…...
Qt应用开发(基础篇)——向导对话框 QWizard
一、前言 QWizard类继承于QDialog,为有向导界面需求的应用环境提供了一个框架。 对话框窗口 QDialog QWizard向导对话框是一个拥有队列界面的特殊对话框,向导的目的是引导用户一步一步的完成预设的流程。向导常用于软件安装界面向导、硬件线路安装向导、…...
Python类的方法
Python类的方法主要分为实例方法、类方法和静态方法三种。 1 实例方法 以self作为第一个参数的方法,就是类的实例方法。该方法由类的实例调用,Python会把调用该方法的实例对象传递给self。 如下代码定义了一个名为A的类。 class A:def __init__(self…...
变电站自动化监控系统
力安科技变电站自动化监控系统是以箱式变电站为管理对象,加装箱变网关,在完成箱变智能化改造的基础上,依托电易云,构建一体化智慧箱变及运维系统。智能箱式变电站被广泛应用于住宅小区、城市公用变压器、工厂、商场、机场、电站等…...
MySql学习笔记11——DBA命令介绍
DBA命令 数据导入 要进入Mysql 创建数据库 create database database_name;使用数据库 use database_name;初始化数据库 source .sql文件地址,不能加双引号;数据导出 要在windows的dos环境下进行 导出数据库 mysqldump database_name > 存放…...
Webpack 复习小结
nodejs学习参考 node常用命令: node xxx.js 执行js文件 npm init -y 初始化package.json npm i 软件包名 下载软件包到本地 npm i 软件包名 -g 下载软件包到全局 npm uni 软件包名 删除软件包 系统优化CDN使用 CDN for free 需求:开发模式使用本地第三…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道
文/法律实务观察组 在债务重组领域,专业机构的核心价值不仅在于减轻债务数字,更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明,合法债务优化需同步实现三重平衡: 法律刚性(债…...
Spring Boot 与 Kafka 的深度集成实践(二)
3. 生产者实现 3.1 生产者配置 在 Spring Boot 项目中,配置 Kafka 生产者主要是配置生产者工厂(ProducerFactory)和 KafkaTemplate 。生产者工厂负责创建 Kafka 生产者实例,而 KafkaTemplate 则是用于发送消息的核心组件&#x…...
