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 需求:开发模式使用本地第三…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...

快速排序算法改进:随机快排-荷兰国旗划分详解
随机快速排序-荷兰国旗划分算法详解 一、基础知识回顾1.1 快速排序简介1.2 荷兰国旗问题 二、随机快排 - 荷兰国旗划分原理2.1 随机化枢轴选择2.2 荷兰国旗划分过程2.3 结合随机快排与荷兰国旗划分 三、代码实现3.1 Python实现3.2 Java实现3.3 C实现 四、性能分析4.1 时间复杂度…...
电脑桌面太单调,用Python写一个桌面小宠物应用。
下面是一个使用Python创建的简单桌面小宠物应用。这个小宠物会在桌面上游荡,可以响应鼠标点击,并且有简单的动画效果。 import tkinter as tk import random import time from PIL import Image, ImageTk import os import sysclass DesktopPet:def __i…...