一文搞懂设计模式之代理模式

news2024/11/24 12:05:51

大家好,我是晴天,本周我们又见面了。本周有点发烧感冒,更文有点慢了,请大家见谅。言归正传,本周我们继续一起学习一文搞懂设计模式系列文章之代理模式。

代理模式-本文目录

什么是代理模式

我们先来看看 GoF 对代理模式的定义:

Provide a surrogate or placeholder for another object to control access to it. ——— GoF
即:代理模式为一个对象提供一种代理以控制对该对象的访问。

代理模式属于结构型设计模式,它能够代替客户向服务提供者发起请求,并且可以在请求服务提供者的前后做一些其他方面的处理。

为了便于我们的理解,接下来借助一个具体的场景理解代理模式。

场景

假设你很喜欢海外购物,喜欢购买韩国的化妆品,喜欢购买美国的生鱼片。在没有代理商的年代里,你只能亲自飞到韩国卖化妆品的店去购买化妆品,飞到美国的生鱼片店去购买生鱼片。你买完这些商品之后,回国进海关的时候,你还需要接受安检并依法补交税款,然后你才能带着这些商品回家享用。这一整个过程是相当费时而且繁琐的,每次你都难免会为出海购物而感都头疼。这时候,一个名叫“胖墩墩”的代理商出现了,他能够去韩国买对应的化妆品、去美国买你要的生鱼片并通过海关的安检带回国,然后向你出售韩国化妆品和美国生鱼片,这样就不需要你亲自出国购买而且也不需要你过海关安检,你只需要付钱给“胖墩墩”,然后在家等着收货就行了。

从这个场景中,我们看到,代理去韩国买了你想要的化妆品,去美国买了你喜欢的生鱼片,并且通过海关带回了祖国,你只需要付钱给代理,就可以在家等着收货了。我们现在就可以清晰代理是什么了,代理能够代替服务提供商(韩国化妆品店和美国生鱼片店)向你提供服务,并且还能够额外提供更多的服务(通过海关安检交税),因此在你看来,跟代理买东西和直接跟服务提供商买东西无异。

为什么需要代理模式

代理模式类图
我们来看一下代理模式的类图
首先定义一个抽象的服务提供商 shopping,它能够提供 Buy(good)购买商品的方法,它的子类有具体的韩国服务提供商和美国服务提供商,以及代理商,都需要实现 Buy(good)方法,代理商还有一个CheckIn(good)的额外方法,用于海关安检,代理商需要依赖于具体的服务提供商(韩国服务提供商和美国服务提供商)。客户端可以直接跟接口进行交互。

通过上面的场景,这个问题就很好说明了。

  1. 代理可以把原始的服务提供商封装起来,向我们提供服务
  2. 代理可以提供额外更强劲的功能
  3. 代理的使用方法和原始服务提供商无异

如何使用代理模式

下面我们把上面的场景写成代码,一起来学习一下

package main

import "fmt"

// 代理模式
// 定义需要购买的商品的结构
type Good struct {
	Name     string
	Producer string
}

// 抽象层
// 服务提供商的抽象化定义   向我们提供Buy(good) 方法
type Shopping interface {
	Buy(good Good)
}

// 实现层
// 韩国购物
type KoreaShopping struct {
}

func (k *KoreaShopping) Buy(good Good) {
	fmt.Println("购买了一件韩国商品:", good.Name)
}

// 美国购物
type AmericaShopping struct {
}

func (a *AmericaShopping) Buy(good Good) {
	fmt.Println("购买了一件美国商品:", good.Name)
}

// 代理类,用于封装韩国购物和美国购物对象
type ShoppingProxy struct {
	// 继承抽象结构,用于后续传入具体韩国购物对象和美国购物对象,从而实现多态功能
	shopping Shopping
}

func NewShoppingProxy(shopping Shopping) ShoppingProxy {
	return ShoppingProxy{
		shopping: shopping,
	}
}

func (s *ShoppingProxy) Buy(good Good) {
	s.shopping.Buy(good)
	s.CheckIn(good)
}

func (s *ShoppingProxy) CheckIn(good Good) {
	if good.Producer == "america" {
		fmt.Printf("对美国购买的商品:%v,缴税并加征%v关税\n", good.Name, "120%")
	} else if good.Producer == "korea" {
		fmt.Printf("对韩国购买的商品:%v,缴税并加征%v关税\n", good.Name, "100%")
	}
}

// 业务逻辑层
func main() {
	g1 := Good{
		Name:     "韩国化妆品",
		Producer: "korea",
	}
	g2 := Good{
		Name:     "美国生鱼片",
		Producer: "america",
	}
	k_shopping := &KoreaShopping{}
	var shopping ShoppingProxy
	shopping = NewShoppingProxy(k_shopping)
	shopping.Buy(g1)
	a_shopping := &AmericaShopping{}
	shopping = NewShoppingProxy(a_shopping)
	shopping.Buy(g2)
}


/*
  输出结果:
  购买了一件韩国商品: 韩国化妆品
  对韩国购买的商品:韩国化妆品,加征100%关税
  购买了一件美国商品: 美国生鱼片
  对美国购买的商品:美国生鱼片,加征120%关税
*/
代码解释:

我们定义了抽象服务提供商 shopping,也定义了具体的服务提供商 koreaShopping 和 AmericaShopping 以及代理ShoppingProxy,他们都实现了Buy(good)方法,代理还额外增加了CheckIn(good Good)方法,用于海关安检。在业务逻辑层,定义了两种商品(韩国化妆品和美国生鱼片),实例化了具体的韩国服务提供商和美国服务提供商,并传入代理中,用于代理对他们进行管理。

代理模式的优点:
  1. 能够一定程度上实现业务逻辑和具体的服务提供商的解耦,协调服务调用者和服务提供商之间的关系
  2. 业务逻辑层可以面向接口编程,符合开闭原则,扩展起来比较方便
代理模式的缺点:
  1. 代理类比较复杂庞大,所有实现的逻辑都堆叠在代理类中,不方便维护。

总结

本文,我们一起学习了什么是代理模式以及为什么需要代理模式,通俗一点理解,代理就是能够对具体的服务对象进行统一管理,并且代替服务对象向我们提供服务,我们请求服务时,只需要向代理请求即可,无需直接向具体的服务对象请求服务,此外代理还可以增加一些其他功能为我们提供更强的服务。

写在最后

感谢大家的阅读,晴天将继续努力,分享更多有趣且实用的主题,如有错误和纰漏,欢迎留言给予指正。 更多文章敬请关注作者个人公众号 晴天码字。 我们下期不见不散,to be continued…

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

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

相关文章

HarmonyOS真机调试报错:INSTALL_PARSE_FAILED_USESDK_ERROR处理

1、 新建应用时选择与自己真机匹配的sdk版本 查看自己设备sdk版本 创建时先择匹配版本: 2、 根据报错提示连接打开处理方案 3、查询真机版本对应的compileSdkVersion 和 compatibleSdkVersion 提示3.1版本之后和3.1版本之前的不同命令(此处为3.0版…

Git企业开发级讲解(四)

📘北尘_:个人主页 🌎个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上,不忘来时的初心 文章目录 一、理解分⽀二、创建分支三、切换分⽀四、合并分⽀五、删除分⽀六、合并冲突七、分⽀管理策略…

轻量封装WebGPU渲染系统示例<34>-数据驱动之Json构建场景

场景和数据之间的互通: 场景数据化或者数据化场景,是当前的主流场景数据构成方式。方便传输方便交换甚至是交互。 内置数据互通机制更有利于用户在各种应用场合下实现具体的3D相关的应用需求。用户只需要关心标准的或者约定好的数据定义及操作方式就能方…

PostgreSQL 入门

文章目录 PostgreSQL介绍PostgreSQL和MySQL的区别PostgreSQL的安装PostgreSQL的配置远程连接配置配置数据库的日志 PostgreSQL基本操作用户操作权限操作 图形化界面安装总结 PostgreSQL介绍 PostgreSQL是一个功能强大的 开源 的关系型数据库,底层基于C实现。其开源…

Sam Altman 被罢免细节曝光,投资 100+ 公司或成「话柄」?

2022 年 11 月,ChatGPT 发布掀起 AI 狂潮。时隔 1 年,2023 年 11 月,ChatGPT 之父、Sam Altman 的一项人事巨变,再次掀起了一场 AI 界的风暴,只是这次并不是技术革命,而是 OpenAI 巨头换帅——Sam Altman 被…

YOLO目标检测——烟雾检测数据集下载分享【含对应voc、coco和yolo三种格式标签】

实际项目应用:烟雾检测数据集可用于监控烟雾情况,实现火灾的早期预警。数据集说明:烟雾检测数据集,真实场景的高质量图片数据,数据场景丰富,含烟雾1个类别标签说明:使用lableimg标注软件标注&am…

QtCreator开发环境的安装和配置

QtCreator开发环境的安装和配置 介绍下载与安装环境介绍示例新建工程示例程序 帮助模式Qt Designer(设计师)Qt Linguist(预言家)结论 介绍 Qt Creator是一个跨平台、完整的集成开发环境(IDE),专门用于Qt开发。它包含了完整的编辑器、调试器和…

数据结构 栈与队列详解!!

一.栈 关于内存中的栈和数据结构中的栈是不同的,本章着重讲的是数据结构的栈。 这是一张关于栈的表达图。从图中可以看出栈很像是一副卡牌,发牌时只能从上取出,即出栈。 而入栈则是像你出牌后,要把你出的牌压在上一张出的牌上面。…

Android跨进程通信,IPC,RPC,Binder系统,C语言应用层调用

文章目录 Android跨进程通信,IPC,RPC,Binder系统,C语言应用层调用()1.概念2.流程3.bctest.c3.1 注册服务,打开binder驱动3.2 获取服务 4.binder_call Android跨进程通信,IPC&#xf…

Swagger示例

对于项目完成后不用写文档,好处还是蛮大的 不需要关注项目其他 只关注接口与实体类即可 SpringBoot项目 依赖 <!--Swagger依赖--> <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version…

Vue3 插槽 v-slot

插槽 视频链接&#xff1a;尚硅谷vue-插槽章节 不使用插槽的情况下 结果&#xff1a; 1 默认插槽 结果&#xff1a; 2 具名插槽 #b是v-slot:b 的缩写 顾名思义就是指着名字去插入 结果&#xff1a; 3 作用域插槽 可以传递数据的插槽&#xff0c;子组件可以将数据回…

​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​

软考-高级-系统架构设计师教程&#xff08;清华第2版&#xff09;【第15章 面向服务架构设计理论与实践&#xff08;P527~554&#xff09;-思维导图】 课本里章节里所有蓝色字体的思维导图

经典ctf ping题目详解 青少年CTF-WEB-PingMe02

题目环境&#xff1a; 根据题目名称可知 这是一道CTF-WEB方向常考的知识点&#xff1a;ping地址 随便ping一个地址查看接受的数据包?ip0.0.0.0 有回显数据&#xff0c;尝试列出目录文件 堆叠命令使用’;作为命令之间的连接符&#xff0c;当上一个命令完成后&#xff0c;继续执…

【数字人】7、GeneFace++ | 使用声音驱动的面部运动系数作为 condition 来指导 NeRF 重建说话头

文章目录 一、背景二、相关工作2.1 唇形同步的 audio-to-motion2.2 真实人像渲染 三、方法3.1 对 GeneFace 的继承3.2 GeneFace 的结构3.2.1 Pitch-Aware Audio-to-Motion Transform3.2.2 Landmark Locally Linear Embedding3.2.3 Instant Motion-to-Video Rendering 四、效果 …

谷歌投资Character.AI,展现AI领域的战略布局和创新能力

谷歌&#xff08;Google&#xff09;作为全球最大的互联网公司之一&#xff0c;一直在人工智能&#xff08;AI&#xff09;领域发挥着引领和推动的作用。近日&#xff0c;据消息人士透露&#xff0c;谷歌正与人工智能初创公司 Character.AI 进行投资谈判&#xff0c;计划投资数…

前端 js 之 promise( 第一版 23.11.18) 09

感觉自己好笨&#xff0c;知识点表达的不够明晰&#xff0c;也正是因为如此&#xff0c;说明有很大的进步空间&#xff0c;更要在此努力&#xff01; 文章目录 前言一、作用二、使用步骤三、promise 类四、promise 方法 前言 每一个新技术的出现&#xff0c;都是解决原有技术上…

Linux网络——HTTP

一.应用层 我们程序员写的一个个解决我们实际问题, 满足我们日常需求的网络程序, 都是在应用层. 我们上一次写的网络版本计算器就是一个应用层的网络程序。 我们约定了数据的读取&#xff0c;一端发送时构造的数据, 在另一端能够正确的进行解析, 就是ok的. 这种约定, 就是应…

电子电器架构 —— 车载网关边缘节点路由转发策略

电子电器架构 —— 车载网关边缘节点路由转发策略 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 PS:小细节,本文字数5000+,详细描述了网关在车载框架中的具体性能设置。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无…

SpringCloud -Token传递之Feign

目录 方法一 RequestHeader 方法二 使用Feign的Interceptor 步骤一 实现RequestInterceptor接口 步骤二&#xff1a;配置Feign 通常微服务对于用户认证信息解析有两种方案 在 gateway 就解析用户的 token 然后路由的时候把 userId 等相关信息添加到 header 中传递下去。在…

观测云助力跨境电商大幅提高加载性能

话不多说&#xff0c;先上结果 什么是用户体验 用户体验基本包含访问网站的性能、可用性和正确性。通俗的讲&#xff0c;就是一把通过用户访问测量【设计者】意图的尺子。 用户体验的基本价值 如果正确实施了终端用户体验&#xff0c;可以第一时间发现&#xff0c;确认影响了…