设计模式-2 结构型模式

news2025/7/24 5:12:10

一、代理模式

1、举例

海外代购

2、代理基本结构图

3、静态代理

1、真实类实现一个接口,代理类也实现这个接口。

2、代理类通过真实对象调用真实类的方法。

4、静态代理和动态代理的区别

1、静态代理在编译时就已经实现了,编译完成后代理类是一个实际的class文件。

2、动态代理是在运行时动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,再加载到JVM中。

5、JDK动态代理实现

核心:构造代理对象,按JDK要求获取参数,让JDK生成代理对象。

// 生成代理对象 - 核心
Dinner proxy = (Dinner) Proxy.newProxyInstance(classLoader, interfaces, h);
package allwe.testProxy;

/**
 * 定义一个晚餐接口
 */
public interface Dinner {

    void eat(String foodName);

    void drink(String juiceName);
}
package allwe.testProxy;

import lombok.Data;

/**
 * 定义人 - 实现晚餐接口
 */
@Data
public class Person implements Dinner {

    private String name;

    public Person(String name) {
        this.name = name;
    }

    @Override
    public void eat(String foodName) {
        System.out.println(this.name + "吃" + foodName);
    }

    @Override
    public void drink(String juiceName) {
        System.out.println(this.name + "喝" + juiceName);
    }
}
package allwe.testProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 我的调用处理器 - 设定增强规则
 */
public class MyInvocationHandler implements InvocationHandler {

    private final Dinner dinner;

    public MyInvocationHandler(Dinner dinner) {
        this.dinner = dinner;
    }

    /**
     * 定义增强规则
     *
     * Object proxy     代理对象
     * Method method    被代理的方法
     * Object[] args    被代理方法运行时的实参
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        if (method.getName().equals("eat")) {
            System.out.println("前置增强===================饭前洗手");
            // 运行eat方法
            method.invoke(dinner, args);
            System.out.println("后置增强===================饭后洗碗");
        } else if (method.getName().equals("drink")) {
            System.out.println("前置增强===================打开瓶盖");
            // 运行eat方法
            method.invoke(dinner, args);
            System.out.println("后置增强===================关上瓶盖");
        } else {
            return method.invoke(dinner, args);
        }
        return null;
    }
}
package allwe.testProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

/**
 * 动态代理实现
 */
public class TestProxy {

    // 通过Proxy动态代理获取一个代理对象,在代理对象中,对某个方法增强
    public static void main(String[] args) {

        // 创建一个人 - 张三
        Dinner dinner = new Person("张三");

        // 被代理对象的类加载器
        ClassLoader classLoader = dinner.getClass().getClassLoader();
        // 被代理对象所实现的所有接口
        Class<?>[] interfaces = dinner.getClass().getInterfaces();
        // 执行处理器对象 - 专门用于定义增强的规则的
        InvocationHandler h = new MyInvocationHandler(dinner);

        // 生成代理对象 - 核心
        Dinner proxy = (Dinner) Proxy.newProxyInstance(classLoader, interfaces, h);

        // 使用代理对象调用Dinner接口的方法
        proxy.eat("馒头");
        proxy.drink("可乐");
    }
}

6、Cglib动态代理实现

核心:构造代理对象,按CGLIB要求获取参数,让CGLIB生成代理对象。

// 1.创建一个Enhancer对象
Enhancer enhancer = new Enhancer();
// 2.设置真实对象的类
enhancer.setSuperclass(personClass);
// 3.设置增强逻辑
enhancer.setCallback(methodInterceptor);
// 4.创建代理对象
Person personProxy = (Person) enhancer.create();
package allwe.testCGLib;

import lombok.Data;

/**
 * 定义人
 */
@Data
public class Person {

    private String name;

    // Cglib使用这个构造器创建真实对象
    public Person() {
        this.name = "张三";
    }

    public void eat(String foodName){
        System.out.println(this.name + "吃" + foodName);
    }
}
package allwe.testCGLib;

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * 我的方法拦截器 - 定义方法拦截规则
 */
public class MyMethodInterceptor implements MethodInterceptor {

    /**
     * Object o                    生成之后的代理对象
     * Method method               父类中原本要执行的方法
     * Object[] objects            方法在被调用时接收的实参
     * MethodProxy methodProxy     子类中重写的  父类方法
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("==========前置增强==========");

        // 执行子类对象方法   -->  son.super.method(args)
        Object res = methodProxy.invokeSuper(o, objects);

        System.out.println("==========后置增强==========");
        return res;
    }
}
package allwe.testCGLib;

import org.junit.jupiter.api.Test;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;

public class TestCglib {

    @Test
    public void testCglib() {
        // 获取被代理的类
        Class<? extends Person> personClass = Person.class;
        // 定义增强规则
        MethodInterceptor methodInterceptor = new MyMethodInterceptor();

        // 获取一个Person的代理对象
        // 1.创建一个Enhancer对象
        Enhancer enhancer = new Enhancer();
        // 2.设置真实对象的类
        enhancer.setSuperclass(personClass);
        // 3.设置增强逻辑
        enhancer.setCallback(methodInterceptor);
        // 4.创建代理对象
        Person personProxy = (Person) enhancer.create();

        // 使用代理对象执行方法
        personProxy.eat("米饭");
    }
}

二、桥接模式

1、定义

在软件开发中,桥接模式将两个独立变化的维度进行了解耦,不是将两者耦合在一起,形成多继承的结构。

2、举例

毛笔和蜡笔,大中小号,12种颜色。

3、结构:实体与行为分离

4、核心

首先要识别出一个类所具有的两个独特的变化维度,将它们设计为两个独立的继承等级结构,为两个维度都提供抽象层,并建立抽象

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

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

相关文章

大量企业系统超龄服役!R²AIN SUITE 一体化企业提效解决方案重构零售数智化基因

《中国百货商业协会2024零售IT及数字化系统需求调查报告》为我们呈现了零售企业在数字化转型中的复杂图景。数据显示&#xff0c;82%的企业高管对AI改变行业未来充满信心 source&#xff1a;中国百货商业协会 &#xff0c;零售IT及数字化系统需求调查报告 &#xff0c;2024年 但…

Cesium使用glb模型、图片标记来实现实时轨迹

目录 1、使用glb模型进行实时轨迹 2、使用图片进行实时轨迹 基于上一篇加载基础地图的代码上继续开发 vue中加载Cesium地图&#xff08;天地图、高德地图&#xff09;-CSDN博客文章浏览阅读164次。vue中加载Cesium三维地球https://blog.csdn.net/ssy001128/article/details…

Android基础回顾】六:安卓显示机制Surface 、 SurfaceFlinger、Choreographer

在 Android 系统中&#xff0c;Surface 和 SurfaceFlinger 是图形渲染系统的核心组件&#xff0c;负责屏幕显示内容的合成与管理。它们协同工作&#xff0c;使各种 App 和系统界面能够高效地显示在屏幕上。 1 Surface 是什么&#xff1f; Surface 是一个抽象的图形缓冲区接口…

敏捷开发中如何避免过度加班

在敏捷开发过程中避免过度加班&#xff0c;需要明确敏捷原则、合理规划迭代任务、加强团队沟通、优化流程效率、设定合理的工作负荷、注重团队士气和成员健康。明确敏捷原则&#xff0c;即保证可持续发展的步调&#xff0c;避免频繁地变更需求、过度承诺任务量。合理规划迭代任…

第1章_数据分析认知_知识点笔记

来自&#xff1a;数据分析自学课程-戴戴戴师兄 逐字稿&#xff1a;【课程4.0】第1章_分析认知_知识点笔记 【课程4.0】第1章 分析认知 知识点总结 数据分析的核心价值不是工具&#xff0c;而是用数据驱动业务增长。 一、数据分析的本质认知 数据分析是什么&#xff1f; 不是酷…

111页可编辑精品PPT | 华为业务变革框架及战略级项目管理华为变革管理华为企业变革华为的管理模式案例培训

这份文档是关于华为公司业务变革管理框架&#xff08;BTMS&#xff09;V2.0的详细介绍&#xff0c;涵盖从年度规划到项目执行的全流程管理。BTMS框架通过变革战略规划、年度规划流程、解决方案开发&#xff08;PMOP流程&#xff09;、运作管理流程等多个模块&#xff0c;系统地…

html文字红色粗体,闪烁渐变动画效果

1. 代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>红色粗体闪烁文字表格</title><s…

Linux文件系统详解:从入门到精通

无论是开发高性能应用还是进行系统级编程&#xff0c;文件系统都是我们必须掌握的基础知识。今天&#xff0c;我将带大家深入浅出地了解Linux文件系统的核心概念和工作原理。 一、Linux文件系统概述 Linux文件系统是操作系统中负责管理持久存储设备上数据的子系统。它不仅仅是…

Electron Fiddle使用笔记

文章目录 下载界面示意图保存和打开项目save 和 save as forge project 其他文档打包报错 RequestError: read ECONNRESET 想要打包前端程序&#xff0c;奈何本地环境总是报错&#xff0c;意外发现可以通过electron fiddle直接调试代码。 下载 百度网盘地址&#xff1a; 首次…

企业培训学习考试系统源码 ThinkPHP框架+Uniapp支持多终端适配部署

在数字化转型浪潮下&#xff0c;企业对高效培训与精准考核的需求日益迫切。一套功能完备、多终端适配且易于定制的培训学习考试系统&#xff0c;成为企业提升员工能力、检验培训成果的关键工具。本文给大家分享一款基于 ThinkPHP 框架与 Uniapp 开发的企业培训学习考试系统&…

SpringBoot手动实现流式输出方案整理以及SSE规范输出详解

背景&#xff1a; 最近做流式输出时&#xff0c;一直使用python实现的&#xff0c;应需求方的要求&#xff0c;需要通过java应用做一次封装并在java侧完成系统鉴权、模型鉴权等功能后才能真正去调用智能体应用&#xff0c;基于此调研java实现流式输出的几种方式&#xff0c;并…

深入解析I²C总线接口:从基础到应用

IC总线概述与基本概念 一句话概述&#xff1a;本章节将介绍IC总线的历史、定义及其在嵌入式系统中的作用&#xff0c;帮助读者建立对IC的基本理解。 IC&#xff08;Inter-Integrated Circuit&#xff09;总线是一种广泛应用于嵌入式系统中的串行通信协议&#xff0c;最初由飞利…

Sklearn 机器学习 缺失值处理 检测数据每列的缺失值

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在代码与灵感交织的数字世界里和大家相遇~💖 ✨ 在这个技术浪潮奔涌的时代,我们既是探索者,也是分享者。我始终相信,每一行代码都是通往创新的钥匙,而分享则能让这把钥匙照亮更多人的…

STL解析——list的使用

目录 1.简介 2.构造函数 3.迭代器 3.1封装 3.2迭代器分类 4.排序性能 4.1链式与数组 4.2缓存读取 1.简介 STL容器中提供的list容器也是一种顺序容器&#xff0c;底层实现方式是带头双向链表&#xff0c;这种实现方式能比单链表更高效的访问数据。 下面围绕部分重要接口…

MQTTX连接阿里云的物联网配置

本文的目标是通过MQTTX的客户端&#xff0c;连接到阿里云的物联网的平台&#xff0c;发送温度信息&#xff0c;在阿里云的平台中显示出来。阿里云免费注册&#xff0c;免费有一个MQTT的服务器。有数量限制&#xff0c;但是对于测试来讲&#xff0c;已经足够。 1、注册阿里云的物…

20250606-C#知识:匿名函数、Lambda表达式与闭包

C#知识&#xff1a;匿名方法、Lambda表达式与闭包 闭包乍一听感觉很复杂&#xff0c;其实一点也不简单 1、匿名方法 没有方法名的方法一般用于委托和事件 Func<int, int, int> myAction delegate(int a, int b) { return a b; }; Console.WriteLine( myAction(1, 2)…

衡量嵌入向量的相似性的方法

衡量嵌入向量的相似性的方法 一、常见相似性计算方法对比 方法核心原理公式优点缺点适用场景余弦相似度计算向量夹角的余弦值,衡量方向相似性,与向量长度无关。$\text{cos}\theta = \frac{\mathbf{a} \cdot \mathbf{b}}{\mathbf{a}\mathbf{b}欧氏距离计算向量空间中的直线距离…

API是什么意思?如何实现开放API?

目录 一、API 是什么 &#xff08;一&#xff09;API 的定义 &#xff08;二&#xff09;API 的作用 二、API 的类型 &#xff08;一&#xff09;Web API 1. RESTful API 2. SOAP API &#xff08;二&#xff09;操作系统 API &#xff08;三&#xff09;数据库 API …

Python训练第四十六天

DAY 46 通道注意力(SE注意力) 知识点回顾&#xff1a; 不同CNN层的特征图&#xff1a;不同通道的特征图什么是注意力&#xff1a;注意力家族&#xff0c;类似于动物园&#xff0c;都是不同的模块&#xff0c;好不好试了才知道。通道注意力&#xff1a;模型的定义和插入的位置通…

第2天:认识LSTM

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 目标 具体实现 &#xff08;一&#xff09;环境 语言环境&#xff1a;Python 3.10 编 译 器: PyCharm 框 架: pytorch &#xff08;二&#xff09;具体步骤…