【代理设计模式详解】C/Java/JS/Go/Python/TS不同语言实现

news2024/12/23 2:40:21

简介

代理模式(Proxy Pattern)是一种结构型设计模式,用一个类来代理另一个类或几个类的功能。

在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。

延迟初始化(虚拟代理)。如果你有一个偶尔使用的重量级服务对象,一直保持该对象运行会消耗系统资源时,可使用代理模式。

访问控制(保护代理)。如果你只希望特定客户端使用服务对象,这里的对象可以是操作系统中非常重要的部分,而客户端则是各种已启动的程序 (包括恶意程序), 此时可使用代理模式。

作用

  1. 为其他对象提供一种代理访问的方式。
  2. 避免直接访问可能带来的问题,通过接口和代理来实现高扩展。

实现步骤

  1. 定义一个基础接口,约定一些方法。
  2. 建立原始类,实现接口方法。
  3. 再建立代理类,也实现基础接口。代理类调用原始类来实现功能。

UML

proxy-pattern.png

Java代码

代理接口类

// Image.java 定义一个接口供代理和实际调用来使用
public interface Image {
  void display();
}

功能代理类

// ProxyImage.java 代理类也实现了基础接口
public class ProxyImage implements Image {

  private RealImage realImage;
  private String fileName;

  public ProxyImage(String fileName) {
    this.fileName = fileName;
  }

  @Override
  public void display() {
    System.out.println("ProxyImage::display() " + fileName);
    if (realImage == null) {
      realImage = new RealImage(fileName);
    }
    // 代理类调用真实类的方法
    realImage.display();
  }
}

真实功能类

// RealImage.java 真实类也实现基础代理接口
public class RealImage implements Image {

  private String fileName;

  public RealImage(String fileName) {
    // 在初始化时执行内部逻辑
    this.fileName = fileName;
    loadFromDisk(fileName);
  }

  @Override
  public void display() {
    System.out.println("RealImage::display() " + fileName);
  }

  // 这个方法只是内部使用
  private void loadFromDisk(String fileName) {
    System.out.println("RealImage::loadFromDisk()  " + fileName);
  }
}

测试调用

  /**
   * 代理模式就是用一个类来代理另一个类或几个类的功能,以便隔绝外部客户和内部真实类
   * 这样真实类和调用方之间有一个代理屏障,保证了安全
   * 同时真实的类如果初始化过,就不再初始化,提升了性能
   */

    // 声明代理类来执行真实类的能力
    Image image = new ProxyImage("001.jpg");

    // 代理类执行真实类的能力
    image.display();

    // 再调用一次,不会重复实例化
    image.display();

Go代码

代理接口类

// Image.go 定义一个接口供代理和实际调用来使用
type Image interface {
  Init(fileName string)
  Display()
}

功能代理类

// ProxyImage.go 代理类也实现了基础接口
type ProxyImage struct {
  fileName string
  // 直接聚合真实类
  // realImage RealImage
  // 聚合接口
  realImage Image
}

// 设置文件名称
func (p *ProxyImage) SetFileName(fileName string) {
  p.fileName = fileName
}

func (p *ProxyImage) Display() {
  fmt.Println("ProxyImage::Display() " + p.fileName)
  if p.realImage == nil {
    p.realImage = &RealImage{}
    p.realImage.Init(p.fileName)
  }
  // 代理类调用真实类的方法
  p.realImage.Display()
}

真实功能类

// RealImage.go 真实类也实现基础代理接口
type RealImage struct {
  fileName string
}

// 在初始化时执行内部逻辑
func (r *RealImage) Init(fileName string) {
  r.fileName = fileName
  r.LoadFromDisk(fileName)
}

func (r *RealImage) Display() {
  fmt.Println("RealImage::Display() " + r.fileName)
}

// 这个方法只是内部使用
func (r *RealImage) LoadFromDisk(fileName string) {
  fmt.Println("RealImage::LoadFromDisk()  " + fileName)
}

测试调用

func main() {
  fmt.Println("test start:")
  /**
   * 代理模式就是用一个类来代理另一个类或几个类的功能,以便隔绝外部客户和内部真实类
   * 这样真实类和调用方之间有一个代理屏障,保证了安全
   * 同时真实的类如果初始化过,就不再初始化,提升了性能
   */

  // 声明代理类来执行真实类的能力
  var image = &src.ProxyImage{}
  image.SetFileName("001.jpg")

  // 代理类执行真实类的能力
  image.Display()

  // 再调用一次,真实类不会重复实例化
  image.Display()
}

C代码简版

// simple_proxy.c
#include <stdio.h>

// 代理模式就是用一个类来代理另一个类或几个类的功能,以便隔绝外部客户和内部真实类

// 定义接口
typedef struct Interface
{
    void (*method)(struct Interface *interface);
} Interface;

// 实现接口的具体类
typedef struct Concrete
{
    void (*method)(struct Concrete *interface);
} Concrete;

void real_method(struct Concrete *interface)
{
    printf("调用真实方法 real_method.\n");
}

// 代理类,继承接口,聚合具体类实例
typedef struct Proxy
{
    struct Interface *real_subject;
} Proxy;

// 代理类方法实现,通过聚合的具体类实例来调用具体类的方法
void proxy_method(struct Interface *interface)
{
    struct Proxy *p = (struct Proxy *)interface;
    p->real_subject->method((struct Interface *)p);
}

int main()
{
    // 创建具体类实例
    struct Concrete real_subject = {
        .method = &real_method,
    };

    // 创建代理类实例并聚合具体类实例
    struct Proxy proxy_instance = {
        .real_subject = (struct Interface *)&real_subject,
    };

    // 将代理类的方法指针指向代理类的方法实现
    struct Interface proxy_interface = {
        .method = &proxy_method,
    };

    // 通过代理类的接口调用具体类方法
    proxy_interface.method((struct Interface *)&proxy_instance);

    return 0;
}

更多语言版本

不同语言实现设计模式:https://github.com/microwind/design-pattern

 

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

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

相关文章

Talk预告 | AAAI‘23 Oral 北京大学陈嘉毅:自然条件下基于三维点云的手物联合位姿追踪与重建

本期为TechBeat人工智能社区第488期线上Talk&#xff01; 北京时间4月6日(周四)20:00&#xff0c;北京大学计算机学院博士——陈嘉毅的Talk将准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “自然条件下基于三维点云的手物联合位姿追踪与重建”&#xf…

iOS - 内存管理

一、App 内存分布 二、OC对象的内存管理 iOS 中&#xff0c;使用引用计数来管理 OC 对象的内存&#xff0c;新创建的 OC 对象引用计数默认是1&#xff0c;当引用计数减为0&#xff0c;OC对象就会销毁&#xff0c;释放其占用的内存空间。调用 retain 会让 OC 对象的引用计数 1&…

perf生成火焰图

文章目录 1&#xff0c;top发现webserver进程空转情况下CPU占用高达200%2&#xff0c;使用性能分析工具perf来进行分析2.1&#xff0c;抓取采集样本2.2&#xff0c;使用perf简单分析性能数据 3&#xff0c;火焰图3.1&#xff0c;生成火焰图3.2&#xff0c;将生成的.svg文件用浏…

电视盒子哪个好?数码小编盘点2023电视盒子排行榜

随着网络剧的热播&#xff0c;电视机又再度受宠&#xff0c;电视盒子也成为不可缺少的小家电。但面对复杂的参数和品牌型号&#xff0c;挑选时不知道电视盒子哪款最好&#xff0c;小编根据销量和用户评价整理半个月后盘点了电视盒子排行榜前五&#xff0c;对电视盒子哪个好感兴…

python编程课后练习答案:一批书几天能买完,勾股数组,个位数字与十位位数字之和除以10所得余数刚好是其百位,剪刀、石头、布猜拳游戏

一、编程题目 编程题目&#xff1a; 4、已知有一批书共1020本&#xff0c;以后每天都买掉一半还多2本&#xff0c;设计程序求出几天能买完。 5、凡是满足x^2y^2z^2的正整数数组(xYz)就称为勾股数组(如345)。请找出任意一个正整数n以内的所有勾股数组 6、编写代码找出满足下面…

不懂如何搭建Web自动化测试环境?这篇文章教你如何上手

摘要&#xff1a; 本文将介绍如何搭建Web自动化测试环境&#xff0c;使用的工具包括Selenium WebDriver和JUnit。同时&#xff0c;本文还提供了详细的代码示例&#xff0c;帮助读者更好地理解和实践相关的知识。 目录 一、前言 二、环境配置 1.安装JDK 2.安装Eclipse 3.下…

对话AI顶尖大牛周明老师:大模型的机遇和挑战?

Datawhale学习 分享人&#xff1a;周明老师&#xff0c;Datawhale 特邀嘉宾 这次 Datawhale开源学习 特别邀请了周明老师分享&#xff1a; 周明&#xff0c;澜舟科技创始人兼CEO&#xff0c;中国计算机学会 CCF 副理事长、NLP和大模型领域的顶尖大牛。 1991年就从NLP重镇哈工大…

typeScript安装以及typeScript配置

1. 什么是typeScript ? 它强调了 TypeScript 的两个最重要的特性——类型系统、适用于任何规模。 包含js的所有的元素&#xff0c;能运行js代码&#xff0c;支持ES语法&#xff0c;是一种开源、跨平台的编程语言。就是js的超 集。 TypeScript 是添加了类型系统的 JavaScri…

Java并发编程 —— ThreadLocal详解

一、什么是ThreadLocal ThreadLocal用于提供线程内部共享的变量&#xff0c;每个线程在访问ThreadLocal实例的时候都可以获得自己的、独立初始化的变量副本&#xff0c;这样线程间互不干扰&#xff0c;从而避免了线程安全问题。 比如我们知道SimpleDateFormat是线程不安全的&…

LVS负载均衡+keepalived高可用

准备准备五台虚拟机 192.168.255.128 MASTER 192.168.255.134 BACKUP 192.168.255.130 Nginx节点服务器1 192.168.255.131 Nginx节点服务器2 192.168.255.132 客户端验证 一、配置节点服务器 1、配置虚接口lo:0 cd /etc/sysconfig/network-scripts/ cp ifcfg-…

Vue-cli 3.x 脚手架搭建的 Vue 2.x 项目进行 npm install 安装时报错: npm ERR! code 1……

项目场景&#xff1a; 公司以前做过的项目&#xff0c;当时开发环境 npm&#xff0c;node.js 版本和现在都不一样&#xff0c;比较旧了&#xff0c;项目之前是用 Vue-cli 3.x 搭建的&#xff0c;Vue 2.x 写的&#xff0c;当时配套的第三方依赖版本也都很落后了&#xff0c;在近…

有趣有爱有温度!迅镭激光第一季度户外团建活动圆满落幕!

阳春四月&#xff0c;元气复苏 凝心聚力&#xff0c;共享喜悦 迅镭激光第一季度寿星及新人 欢聚常熟蒋巷基地 开启一段美妙的户外团建之旅 无创意不团建!蓝天白云下&#xff0c;队员们在教练的指导下解锁各种花样游戏大玩法&#xff0c;大家密切配合、相互协作&#xff0c;…

Docker | 解决docker 容器中csv文件乱码的情况

问题描述&#xff1a;在Ubuntu docker容器中&#xff0c;打开.csv文件时显示乱码 问题如图 错误分析&#xff1a; 用locale查看所用容器支持的字符集 从输出可以看到&#xff0c;系统使用的是POSIX字符集&#xff0c;POSIX字符集是不支持中韩文的&#xff0c;而UTF-8是支持中…

054:cesium加载WMS规范的影像服务

第054个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中加载WMS规范的影像服务。WebMapServiceImageryProvider提供由 Web 地图服务 (WMS) 服务器托管的平铺图像。 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代…

剑指 Offer II 026. 重排链表

思路&#xff1a; &#xff08;1&#xff09;找到链表中心点&#xff0c;如果链表节点为奇数&#xff0c;那么要保证前面要比后面多一个节点。 &#xff08;2&#xff09;将后一部分的结点进行反转。 &#xff08;3&#xff09;将反转后的结点插入前一部分的结点。 &#xff0…

前有谷歌的“生存指南”,后有金山系的“表格编程”,均登热榜

谷歌的“生存指南” 一位曾经在谷歌工作的工程师&#xff0c;干了一件了不起的事&#xff0c;花费了两年的时间&#xff0c;整理了一份“xg2xg”的清单。 原来这位离职的谷歌工程师为程序员编写了一份“厂外生存指南”&#xff0c;即使你从谷歌离职后&#xff0c;在这套“生存…

无良公司把我从上家挖过来,白嫖了六个月,临近试用期结束才说不合适,催我赶紧找下家!...

职场套路多&#xff0c;一不小心就会掉坑&#xff0c;一位网友讲述了自己的遭遇&#xff1a; 今天被领导催促离职了&#xff0c;当时就是这个领导把他从别的公司挖过来。这家公司催得太急&#xff0c;为了投奔这里&#xff0c;他和上家的HR都闹翻了&#xff0c;上家总监挽留他&…

ChatGLM ptuning 的实战方案

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

【中间件】kafka

目录 一、概述二、生产者1. 发送原理2. 生产者分区 Partition分区好处分区策略 3. 生产者如何提高吞吐量4. 数据可靠性ACK应答级别数据不丢失&#xff1a;ACK ISR数据不重复&#xff1a;幂等性数据有序 三、broker1. 工作流程2. 副本相关3. 底层存储4. 高效读写数据 四、消费者…

常见误区,你可曾踩过?深度剖析WEB自动化测试实施问题与解决方案

目录 摘要&#xff1a; 一、WEB自动化测试实施的步骤 1.测试计划 2.测试用例设计 3.环境搭建 4.脚本编写 5.执行测试 6.缺陷管理 二、WEB自动化测试常见误区 1.选择不合适的自动化测试工具和框架 2.忽略测试环境的影响 3.. 缺乏对页面元素的理解 三、示例代码 结论…