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 的类和方法

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

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

相关文章

一维数组笔试题及其解析

Lei宝啊 &#xff1a;个人主页 愿所有美好不期而遇 前言&#xff1a; 数组名在寻常情况下表示首元素地址&#xff0c;但有两种情况例外&#xff1a; 1.sizeof(数组名)&#xff0c;这里的数组名表示整个数组&#xff0c;计算的是整个数组的大小 2.&数组名&#xff0c;这里的…

方差分析的核心概念“方差分解“

方差是统计学中用来衡量数据集合中数值分散或离散程度的一种统计量。它表示了数据点与数据集合均值之间的差异程度&#xff0c;即数据的分散程度。方差越大&#xff0c;表示数据点更分散&#xff0c;而方差越小&#xff0c;表示数据点更集中。 方差的计算公式如下&#xff1a;…

Vue+NodeJS上传图片到腾讯云Cos

一.前端Vue 1.选择图片 --HTML <input type"file" accept"image/*" change"handleFileChange"> <el-button size"large" click"changeAvatar">上传头像</el-button> //选择图片 function handleFileC…

【杂】环形时钟配色笔记

配色网站笔记 coolorsflatuicolorscolordrophttps://www.webdesignrankings.com/resources/lolcolors/ 配色2

Unity中的场景加载

1、同步场景 2、异步加载 public class TestScenesLoad : MonoBehaviour {// Start is called before the first frame updatevoid Start(){StartCoroutine(Load());}// Update is called once per framevoid Update(){}private IEnumerator Load() { //异步加载&#xff0c;常…

【腾讯云Cloud Studio实战训练营】戏说cloud studio

文章目录 前言产品概述项目体验登录空间模板模板项目体验 总结 前言 在奇幻世界中&#xff0c;存在着一片神秘的云海&#xff0c;被人们称为腾讯云云端开发环境 Cloud Studio。这片云海是一座巨大的浮岛&#xff0c;上面漂浮着一个集成式开发环境&#xff08;Integrated Devel…

【STM32RT-Thread零基础入门】8. 基于 CubeMX 移植 RT-Thread Nano

硬件&#xff1a;STM32F103ZET6、ST-LINK、usb转串口工具、4个LED灯、1个蜂鸣器、4个1k电阻、2个按键、面包板、杜邦线 文章目录 前言一、cubemx配置二、board.c文件修改2.rtconfig.h文件修改 三、主程序1. main函数2. task函数 总结 前言 利用RT_Thread操作系统实现三种不同的…

常见的旅游类软文类型分享

假期将至&#xff0c;越来越多人选择出门旅游度过假期&#xff0c;那么各大旅游品牌应该怎么让自己的旅游软文在众多品牌中脱颖而出呢&#xff1f;接下来媒介盒子就给大家分享几个最能吸引受众的旅游类型软文。 一、攻略类软文 和普通的攻略不一样&#xff0c;普通的攻略以用户…

Python函数的概念以及定义方式

一. 前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 二. 什么是函数&#xff1f; 假设你现在是一个工人&#xff0c;如果你实现就准备好了工具&#xff0c;等你接收到任务的时候&#xff0c; 直接带上工…

LeetCode141:环形链表

给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置&#xff08;…

数学建模:回归分析

&#x1f506; 文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 数学建模&#xff1a;回归分析 文章目录 数学建模&#xff1a;回归分析回归分析多元线性回归案例 多项式回归一元多项式回归多元二项式回归 非线性回归逐步回归 回归分析 多元线性回归 案例 首先进行回归分…

无涯教程-Flutter - Dart简介

Dart是一种开源通用编程语言&#xff0c;它最初是由Google开发的&#xff0c; Dart是一种具有C样式语法的面向对象的语言&#xff0c;它支持诸如接口&#xff0c;类之类的编程概念&#xff0c;与其他编程语言不同&#xff0c;Dart不支持数组&#xff0c; Dart集合可用于复制数据…

【Github】git本地仓库建立与远程连接

文章目录 前言一、git简介二、git下载2.1下载地址 三、git安装3.1安装3.2 配置3.3 config设置&#xff08;增删改查&#xff09; 四.github与git连接——本地Git仓库4.1 建本地的版本库4.2 源代码放入本地仓库4.3提交仓库 五、github与git的连接——远程连接5.1 创建SSH Key5.2…

网络地址转换技术NAT(第九课)

一 什么是NAT? NAT是网络地址转换的缩写,是一种在计算机网络中使用的技术,可以将私有地址转换为公共地址,从而实现本地网络与公共网络的互联。NAT工作在网络层,可以隐藏内部网络中的IP地址和端口号,从而增强网络的安全性和灵活性。在家庭网络、企业网络、公共WIFI热点等…

虹科方案|HK-Edgility利用边缘计算和VNF降本增效

一、边缘计算和 VNF 在当今瞬息万变的数字环境中&#xff0c;边缘虚拟化网络功能&#xff08;VNF&#xff09;是一个既能够优化网络基础设施&#xff0c;又能控制成本的创新型解决方案。它使客户能够将多个基于软件的 VNF 整合到一个专用计算设备上。更值得高兴的是&#xff0c…

模型压缩-对模型结构进行优化

模型压缩-对模型结构进行优化 概述 模型压缩通常都是对推断过程而言&#xff0c;训练过程的计算代价通常不考虑&#xff0c;因为GPU可以快速完成任意复杂度模型的训练对于推断过程来说&#xff0c;模型应用才是对于速度敏感的场景多数情况下 希望使用尽可能少的能耗完成京可能…

SpringBoot——整合Mongodb

简单介绍 Mongdb是一个开源&#xff0c;高性能&#xff0c;无模式的文档型数据库&#xff0c;NoSQL数据库产品中的一种&#xff0c;是最像关系型数据库的非关系型数据库。 使用场景 用户数据 存储位置&#xff1a;数据库特征&#xff1a;永久性存储&#xff0c;修改频率极低游…

蠕虫病毒流量分析案例

背景 某供排水集团的网络管理员对其网络的健康状况持认可态度&#xff0c;表示网络运行正常&#xff0c;没有发现异常行为。然而&#xff0c;由于网络环境变得越来越复杂&#xff0c;仅凭借传统的网络经验已经不能全面了解网络情况。因此&#xff0c;我们为供排水集团安装了Ne…

【实训】“宅急送”订餐管理系统(程序设计综合能力实训)

&#x1f440;樊梓慕&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》 &#x1f31d;每一个不曾起舞的日子&#xff0c;都是对生命的辜负 前言 大一小学期&#xff0c;我迎来了人生中的第一次实训…

LNMP架构搭建论坛

目录 一、LNMP简介&#xff1a; 二、LNMP搭建&#xff1a; 1.前提准备&#xff1a; 关闭防火墙和安全机制&#xff1a; 2.编译安装nginx&#xff1a; 3.编译安装mysql&#xff1a; 3.1 安装依赖环境&#xff1a; 3.2 创建mysql运行用户&#xff1a; 3.3 编译安装&#xff1a…