7.javaSE基础进阶_设计模式和代理模式(静态代理JDK和动态代理CGLIB)

文章目录

  • 一.设计模式
    • 1.简介
      • 1)设计模式基本要素
      • 2)设计模式的分类
        • 1.模式依据其目的可分为:
        • 2.第二是范围准则
        • 3.创建模式
        • 4.结构模式
        • 5、行为模式
    • 2.工厂模式
      • 1)定义
      • 2)结构
      • 3)创建工厂
    • 3.单例(Singleton)模式
      • 1)定义
      • 2)应用
      • 3)分类
        • 1.饿汉式EngerSingLeton
        • 2.懒汉式LazySingLeton
    • 4.Prototype模式
      • 1)适应场景
      • 2)结构
  • ...................................................................................................
  • 二.代理模式
    • 1.简介
      • 1)定义:
      • 2)**分类**
      • 3)Proxy模式结构
    • 2.静态代理
      • 1)优缺点
    • 3.动态代理
      • 1)JDK原生动态代理
      • 2)CGLIB动态代理
    • 4.JDK代理与CGLIB代理的区别

一.设计模式

1.简介

设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。

  • 使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。
  • 每个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。
  • 设计模式的贯穿思想:针对接口编程,最大限度的适应变化,实现代码重用

1)设计模式基本要素

  • 模式名称(pattern name):一个助记名, 它用一两个词来描述模式的问题、解决方案和效果。
  • **问题(problem):**描述了应该在何时使用模式它解释了设计问题和问题存在的前因后果,它可能描述了特定的设计问题,如怎样用对象表示算法等。
  • **解决方案(solution):**描述了设计的组成成分,它们之间的相互关系及各自的职责和协作方式。
  • 效果(consequences) : 描述了模式应用的效果及使用模式应权衡的问题。

2)设计模式的分类

1.模式依据其目的可分为:
  • 创建型(Creational) 创建型模式与对象的创建有关
  • 结构型 (Structural) 结构型模式处理类或对象的组合
  • 行为型(Behavioral) 行为型模式对类或对象怎样交互和怎样分配职责进行描述
2.第二是范围准则

指定模式主要是用于类还是用于对象。

  • 类模式:处理类和子类之间的关系,这些关系通过继承建立,是静态的,在编译时刻便确定下来了。
  • 对象模式:处理对象间的关系,这些关系在运行时刻是可以变化的,更具动态性。
3.创建模式

创建模式(Creational Pattern):是对类的实例化过程的抽象化

一些系统在创建对象时,需要动态地决定怎样创建对象、创建哪些对象,创建模式描述了怎样构造和封装这些动态的决定:

  • 工厂方法(Factory Method)
  • 抽象工厂(Abstract Factory)
  • 单例(Singletion)
  • 原型(Prototype)
  • 建造者(Builder)
4.结构模式

结构模式(Structural Pattern):描述如何将类或者对象结合在一起形成更大的结构,结构模式描述了两种不同的东西:类、类的实例

  • 适配器(Adapter)
  • 桥接(Bridge)
  • 组合(Composite)
  • 装饰(Decorator)
  • 外观(Facade)
  • 享元(Flyweight)
  • 代理(Proxy)
5、行为模式

在不同的对象之间划分责任和算法,而且解决对象之间如何相互作用

  • 迭代(Iterator)
  • 模板方法(Template Method)
  • 职责链(Chain of Responsibility)
  • 访问者(Visitor)
  • 中介者(Mediator)
  • 观察者(Observer)
  • 备忘录(Memento)
  • 状态(State)
  • 策略(Strategy)
  • 命令(Command)
  • 解释器(Interpreter)

2.工厂模式

1)定义

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

工厂模式又叫静态工厂方法模式、简单工厂

2)结构

模式的核心是工厂类。这个类含有必要的判断逻辑,可以决定在什么时候创建那一个产品类的实例。而客户端则可以免除直接创建产品对象的责任,而仅仅负责“消费”产品。简单工厂模式通过这种做法实现了对责任的分割

  • 工厂类(Creator)角色:担任这个角色的是工厂模式的核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下创建产品对象,它往往由一个具体Java类实现。
  • 抽象产品(Product)角色:担任这个角色的类是由工厂方法模式所创建的对象的父类,或它们共同拥有的接口。抽象产品角色可以用一个Java接口或者java抽象类实现。
  • 具体产品(Concrete Product)角色:工厂方法模式所创建的任何对象都是这个角色的实例,具体产品角色有一个具体java类实现

创建测试接口及实现类,

3)创建工厂

通过中间的工厂调用其他类的方法

3.单例(Singleton)模式

1)定义

单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

这里有三个要点:

  1. 某个类只能有一个实例
  2. 类必须自行创建这个实例
  3. 以公共、统一的方式向整个系统提供这个实例

2)应用

许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。

比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。

这种方式简化了在复杂环境下的配置管理

借助编程语言自身的语法特性,强制限制某个类,不能创建多个实例

3)分类

1.饿汉式EngerSingLeton

直接创建对象

public class EagerSingleton {private static final EagerSingleton m_instance = new EagerSingleton();private EagerSingleton() {}public static EagerSingleton getInstance() {return m_instance;}
}
2.懒汉式LazySingLeton

先判断在创建对象

public class LazySingleton {private static LazySingleton m_instance = null;private LazySingleton() {}public static LazySingleton getInstance() {if (m_instance == null) {m_instance = new LazySingleton();}return m_instance;}
}

4.Prototype模式

Prototype模式即原型模式,原型模式其实是一个比较单纯的设计模式,其目的就是利用一个原型对象,快速地生成一批对象,从而避免重复的新建过程。

工作原理是:通过将一个原型对象传给一个要新建的对象,新建对象通过请求原型对象拷贝它们,然后自己来实施创建

1)适应场景

主要适用于以下情况:

  • 构建函数相对比较复杂
  • 构建函数不能被不相关的人调用
  • 一批对象中绝大部分对象的属性一致,而只有极少数不同

2)结构

  • Prototype:声明一个克隆自身的接口或抽象类
  • ConcretePrototype:实现一个克隆自身的操作
  • Client:让一个原型来克隆自身从而创建一个新的对象

二.代理模式

1.简介

代理这个词相信大家并不陌生,我们大家都知道代理商,简单地说就是代替厂家卖商品,厂家委托代理为其销售商品,顾客找代理购买商品。

通过使用代理,通常有两个优点,并且能够分别与我们提到的代理商的几个特点对应起来:

  1. 关于代理商,首先我们从他们那里买东西时通常不知道背后的厂家究竟是谁,也就是说,委托者对我们来说是不可见的;
  2. 代理可以对顾客进行定位,更精确的售卖给需要的客户群体

1)定义:

代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。

代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。

代理模式:为其他对象提供一种代理以控制对这个对象的访问,也就是创建一个代理对象作为客户端和目标对象之间的中介,主要目的就是保护目标对象或增强目标对象

通过使用代理模式,通常有以下两个优点:

  1. 可以隐藏被代理类的实现
  2. 可以实现客户与被代理类间的解耦,在不修改被代理类代码的情况下能够做一些额外的处理

2)分类

按照代理的创建时期,代理类可以分为两种。

  • 静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了**
  • 动态代理:在程序运行时,运用反射机制动态创建而成

3)Proxy模式结构

由三部分组成:

  • Proxy:保存一个引用使得代理可以访问实体。控制对实体的存取,并可能负责创建和删除它,其他功能依赖于代理的类型。
  • Subject:定义RealSubject和Proxy的共用接口,这样就在任何使用RealSubject的地方都可以使用Proxy。
  • RealSubject:定义Proxy所代表的实体。

2.静态代理

若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的

所谓的静态代理,就是通过声明一个明确的代理类来访问源对象,一个代理只能服务于一种产品,当有n种产品时,就需要n个代理,这样就不利于业务的发展。

举例:我们有两个接口,Computer和 Phone,每个接口都有一个实现类

  1. 定义接口(代理接口)
  2. 定义实现类(委托类)
  3. 定义代理类Proxy(代理类,最终还是调用委托类实现业务操作)

通过代理类调用的方法调用实现类的方法

1)优缺点

静态代理的代码非常简单易懂,这种模式虽好,但是也有明显的缺点:

  • 会存在大量冗余的代理类,这里只有两个接口,如果有n个接口,那么就要定义n个代理类。
  • 不易维护,一旦接口更改,代理类和被代理类都要更改。

3.动态代理

代理类在程序运行时创建的代理方式被成为 动态代理。 也就是说,这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的指示动态生成的 ,在程序运行时,运用反射机制动态创建而成代理对象。

JDK从1.3版本就开始支持动态代理类的创建。

java.lang.reflect类库中提供三个类直接支持代理模式:ProxyInvocationHandlerMethod

1)JDK原生动态代理

是Java原生支持的,不需要外部依赖,但是它只能基于接口进行代理(需要动态代理的对象必须实现与某个接口)

  1. Proxy类

    Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

    核心方法newProxyInstance:返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)//参数说明:
//loader - 定义代理类的类加载器 interfaces - 代理类要实现的接口列表 h - 指派方法调用的调用处理程序
//Ps:类加载器 在Proxy类中的newProxyInstance()方法中需要一个ClassLoader类的实例,ClassLoader实际上对应的是类加载器
  1. InvocationHandler类

    代理实例的调用处理程序 实现的接口

    每个代码实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法

package java.lang.reflect;
public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;
}
//参数说明:
//Object proxy:在其上调用方法的代理实例。
//Method method:要调用的方法
//Object\[] args:方法调用时所需要的参数
//可以将InvocationHandler接口的子类想象成一个代理的最终操作类,替换掉ProxySubject。
public class JDKProxy implements InvocationHandler {private final Object target;public JDKProxy(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {long start = System.currentTimeMillis();Object obj = method.invoke(target, args);long end = System.currentTimeMillis();System.out.println(method.getName() + "耗时" + (end - start) + "ms");return obj;}
  1. Method类

    Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。

    主要方法invoke:对带有指定参数的指定对象调用由此 Method 对象表示的基础方法

public Object invoke(Object obj,Object... args)
//  参数: obj - 从中调用基础方法的对象 args - 用于方法调用的参数

2)CGLIB动态代理

[CGLIB] https://mvnrepository.com/artifact/cglib/cglib CGLIB

CGLIB通过继承的方式进行代理,(让需要代理的类成为Enhancer的父类),无论目标对象有没有实现接口都可以代理,但是无法处理Final的情况(依赖外包)

  • 引入依赖

    导入cglib-3.1.jarasm-4.2.jar

  • 使用流程

    1. 创建代理对象

    2. 得到委托类

    3. 得到代理类

    4. 通过代理对象调用方法

public class CGLibProxy {public static Object getProxy(final Object target) {//创建enhancer对象Enhancer enhancer = new Enhancer();//创建代理对象为超级类enhancer.setSuperclass(target.getClass());//调用应用enhancer.setCallback(new MethodInterceptor() {/*** @author Arran* @description  * @params [o, method, objects, methodProxy] * @return java.lang.Object * @date  2024/06/27 下午 03:13*/@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("售前咨询 之前被调用");Object result = method.invoke(target, objects);System.out.println("售后处理 之后被调用");return result;}});//创建代理对象return enhancer.create();}
}

4.JDK代理与CGLIB代理的区别

  • JDK动态代理实现接口,CGLIB动态继承思想

  • JDK动态代理(目标对象存在接口时)执行效率高于CIGLIB

  • 如果对象有接口实现,选择JDK代理,如果没有接口实现选择CGILB代

 Object result = method.invoke(target, objects);System.out.println("售后处理 之后被调用");return result;}});//创建代理对象return enhancer.create();
}

}


## 4.JDK代理与CGLIB代理的区别- JDK动态代理实现接口,CGLIB动态继承思想- JDK动态代理(目标对象存在接口时)执行效率高于CIGLIB- 如果对象有接口实现,选择JDK代理,如果没有接口实现选择CGILB代​     

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

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

相关文章

Java学习 - Redis缓存问题与优化

缓存收益与成本 收益 加速读写降低后端、持久层的负载和压力 成本 可能导致数据不一致代码运维成本redis节点运维成本 缓存更新策略 策略一致性维护成本介绍LRU/LIRS算法剔除最差底剔除最近最少使用的数据超时剔除较差底定时删除、惰性删除主动更新最好高持久层更新&#x…

监控 Promethus的监控告警Alertmanager、Grafana

Promethus的监控告警Alertmanager Alertmanager 介绍 Prometheus的一个组件&#xff0c;用于定义和发送告警通知&#xff0c;内置多种第三方告警通知方式&#xff0c;同时还提供了对Webhook通知的支持基于警报规则对规则产生的警报进行分组、抑制和路由&#xff0c;并把告警发…

深入了解Spring框架的模块组成

目录 Spring CoreSpring ContextSpring AOPSpring DAOSpring ORMSpring WebSpring MVCSpring WebFluxSpring TestSpring BootSpring SecuritySpring BatchSpring IntegrationSpring Cloud结论 Spring Core 1.1 核心容器 Spring Core模块是整个Spring框架的基础。它包含了框架…

vue如何引入图标

方法1&#xff1a;iconify/vue pnpm add iconify/vue -D 网址&#xff1a;https://icon-sets.iconify.design/ 使用哪个需要安装 如下截图,安装指令&#xff1a; > npm install iconify/icons-gg在使用的页面引入 import { Icon } from “iconify/vue”; <template>…

Mysql存储过程用法:使用存储过程编程,来判断数据库中数据表中的字段是否重复,避免重复插入记录

目录 一、mysql的存储过程介绍 二、. 创建存储过程 1、准备 2、创建插入记录的存储过程 三. 调用存储过程 四. 删除存储过程 五. 修改存储过程&#xff0c;避免数据表的姓名出现重复 1、修改存储过程的方式 2、重新创建存储过程 六. 验证新的存储过程 1、插入新的记…

高考后的抉择:专业优先还是学校优先?

随着2024年高考的帷幕落下&#xff0c;高考生们面临的一个重要抉择再度浮上心头&#xff1a;在分数受限的情况下&#xff0c;是选择一个心仪的专业&#xff0c;还是选择一个知名度更高的学校&#xff1f;这是一个困扰了众多考生和家长的长期难题。在这个关键的时刻&#xff0c;…

好用的导航网站有哪些

网址导航网站是我们日常上网的一个重要工具。它们不仅可以帮助我们快速找到所需的资源和信息&#xff0c;还能提高我们的工作效率。以下是小编收藏的几个好用的导航网站&#xff0c;涵盖了办公、学习、娱乐等多个领域&#xff0c;分享给大家。 1. 办公人导航 办公人导航是一个…

Drag Select Compose:实现多平台图片多选功能的利器

Drag Select Compose:实现多平台图片多选功能的利器 在现代移动应用开发中,图片多选功能是一个常见且实用的需求。而实现这种功能可能涉及到复杂的手势处理和状态管理。今天,我将介绍一款强大的Compose多平台库——Drag Select Compose,它能够轻松实现类似于Google Photos…

【鸿蒙】第2天・装饰器・组件和页面生命周期

背景知识 &#xff11;・ArkTS 拓展了 TypeScript&#xff0c;TypeScript 拓展了 JavaScript。 增加了一些约束。 &#xff12;・ArkTS 是声明式编程。 构建对象时类似构建者设计模式。链式赋值。 装饰器 &#xff20;Component 自定义组件 Component装饰器仅能装饰str…

BGP中的TCP连接源地址问题

3.TCP连接源地址&#xff08;用loop back地址是最优选择&#xff09; 应用场景与理论&#xff1a; 由于BGP应用于大型网络中&#xff0c;为了避免单点失败&#xff0c;往往需要通过多条链路连接&#xff0c;当一条链路故障时候就用另一条链路继续工作&#xff0c;但是BGP又无法…

为何重要?解析企业实行网络安全等级保护的必要性

在全球信息化迅速发展的背景下&#xff0c;企业数据资产成为核心竞争力的重要组成部分。然而&#xff0c;随之而来的网络安全威胁亦日益严峻&#xff0c;从数据泄露到勒索软件攻击&#xff0c;每一次安全事件都可能给企业带来不可估量的损失。在此情境下&#xff0c;实行网络安…

Java IO: 使用 FileReader 和 FileWriter 进行文件操作

在 Java 中&#xff0c;进行文件操作是一个常见的任务。FileReader 和 FileWriter 是用于读取和写入文本文件的类&#xff0c;它们提供了一种方便的方法来处理文件内容。本文将介绍如何使用 FileReader 和 FileWriter&#xff0c;并提供一些示例代码。 FileReader 类概述 Fil…

使用PHP创建一个简单的Web爬虫

随着互联网的不断发展&#xff0c;信息的获取变得越来越方便。然而&#xff0c;海量的信息也给我们带来了很多的烦恼&#xff0c;如何高效地获取到我们所需要的信息就成了一项非常重要的任务。在实现自动化获取信息的过程中&#xff0c;web爬虫被广泛应用。 Web爬虫是一种自动…

R语言进行字符的替换和删减gsub,substr函数

目录 R语言读文件“-“变成“.“ 提取列字符前几个 提取列字符末尾几个 进行字母替换 paste0函数使用</

学计算机的学生假期可以干什么?

学习目标&#xff1a; 学计算机的学生假期可以干什么 学习内容&#xff1a; 实习&#xff1a;寻找计算机相关领域的实习机会&#xff0c;积累工作经验。这对你未来找工作非常有帮助。在线课程&#xff1a;参加编程、数据科学或其他技术领域的在线课程&#xff0c;提升技能。公…

python实现API调用缓存

python实现API调用缓存 1.代码2.输出3.保存的json数据 想把python某些函数的参数及返回值记录下来,如果之前已计算过,则直接返回缓存中的数据 1.代码 import jsondef get_variable_name(var):变量转变量名local_varsglobals()return [name for name, value in local_vars.ite…

螺旋模型:结合瀑布模型和增量模型的项目管理利器

目录 前言1. 螺旋模型概述1.1 螺旋模型的核心理念1.2 螺旋模型的四个阶段 2. 螺旋模型的详细步骤2.1 计划阶段2.2 风险分析阶段2.3 工程阶段2.4 评估阶段 3. 螺旋模型在大型项目中的应用3.1 应对需求变化3.2 有效的风险管理3.3 增强的客户参与3.4 灵活的资源分配 4. 螺旋模型的…

redis分布式事务

1. 使用RedisTemplate.opsForValue().setIfAbsent(key, value, time, TimeUnit.SECONDS) 这种方法是基于Redis的SET命令的NX&#xff08;Not eXists&#xff09;选项和EX&#xff08;expiry time&#xff09;选项来实现的。它尝试设置一个键值对&#xff0c;只有当键不存在时才…

git-extras

当使用 git-extras 时&#xff0c;除了安装和基本命令之外&#xff0c;了解如何结合常见的 Git 工作流程和实际开发需求会更加有帮助。下面是一个更全面的 git-extras 使用教程&#xff0c;涵盖了安装、常见命令以及实际应用场景的示例。 1. 安装 git-extras 在 macOS 上&…

Java面试题:讨论单例模式的实现方式,包括懒汉式和饿汉式,并讨论线程安全问题

单例模式&#xff08;Singleton Pattern&#xff09;是一种设计模式&#xff0c;确保一个类只有一个实例&#xff0c;并提供一个全局访问点。单例模式在某些场景下很有用&#xff0c;例如配置管理、日志记录等。以下是单例模式的两种主要实现方式&#xff1a;懒汉式&#xff08…