用23种设计模式打造一个cocos creator的游戏框架----(七)代理模式

1、模式标准

模式名称:代理模式

模式分类:结构型

模式意图:为其他对象提供一种代理以控制对这个对象的访问。

结构图:

适用于:

  1. 远程代理:也称为大使,这是最常见的类型,在分布式对象通信中被用于表示运行在不同地址空间的对象。

  2. 虚拟代理:根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象。

  3. 安全代理:用来控制真实对象访问时的权限。

  4. 智能指引:当调用真实对象时,代理处理另外一些事。

代理模式主要有两个角色:

  • 代理(Proxy):保存一个引用使得代理可以访问实体。提供一个与主题的接口相同的接口,这样代理就可以用来替代实体。控制对实体的存取,并可能负责创建和删除它。

  • 实体(Real Subject):代理所代表的真实对象,是真正的被调用的对象。

2、分析与设计 

代理在日常开发中经常用到,比如通过香港服务器代理去看github上的项目。比如通过抓包工具作为代理,将app的请求过程进行拦截修改,然后在发送出去。代理虽然帮你干了你想干是事情,但是你却不知道它其实干了更多你不知道的。代理的玩法有很多,在游戏框架中我们如何使用代理模式,应该也有很多玩法,这里我只介绍其中一种。

在前端开发中vue的作者用在vue3中用proxy来取代vue2的Object.defineProperty实现响应式。游戏中也经常用到数据与视图的绑定,比如玩家的金币,在数据层player.money = 200时,我们希望页面上的所有显示金币数量的地方,都自动自动刷新视图显示为200,且如果数值不变时,你们你触发n多次player.money = 200,都不会触发刷新视图的事件。

3、开始打造

interface IObject {
    operation()
}
class RealObject implements IObject {
    operation() {

    }
}

class ProxyObject implements IObject {
    realObject: RealObject;

    constructor(realObject: RealObject) {
        this.realObject = realObject
    }

    public operation(): void {
        //在调用目标对象之前,完成一些操作
        console.log("Before Do Something");
        this.realObject.operation();
        //在调用目标对象之后,完成一些操作
        console.log("After Do Something");
    }
}

 如果是代理对象,就不用自己写一个了,用内部基于 ES6 的 Proxy 实现就够用了

const vmHandler = {
    set(obj, prop, value) {
        // 代理拦截修改
        obj[prop] = value;
        return true
    }
};
let loading_vm: ILoadingVM = {
        progress: 0
    }
let proxy_loading_vm = new Proxy(loading_vm, vmHandler)

我们的目的是给游戏框架整一个数据绑定的功能,所以这里用 ES6 的 Proxy就够了。

4、开始使用

这里用ES6 的 Proxy自带的那个代理,因为我们主要是对数据修改进行代理拦截

因为之前是考虑到多个游戏分离,所以给每个游戏整了一个IGameVM,目前简单点只给ui做了全局的vm

export class DemoVM implements IGameVM {
 
   /**
     * 
     * 唯一的方法出口
     */
    getVMs() {
        return {
            // loadingVM: this._getLoadingVM(),
            gateVM: this._getGateVM(),
            // battleVM: this._getBattleVM(),
        }
    }   

    /**
     * 动态显示数据
     */
    private proxy_gate_vm: IGateVM_JCQ = null
    private _gate_vm: IGateVM_JCQ = {
        ps: 0,
        gold: 0,
        diamond: 0,
        last_battle_id: 0 // 当前最高关卡
    }
    private _getGateVM() {
        if (!xhgame.gui.getUI(xhgame.uiid.Gate_Index)) {
            return this._gate_vm
        }
        if (this.proxy_gate_vm == null && xhgame.gui.getUI(xhgame.uiid.Gate_Index)) {
            const handler = xhgame.gui.getUI(xhgame.uiid.Gate_Index).getComponent(GateView).vmHandler
            // 设计模式12 代理模式
            this.proxy_gate_vm = new Proxy(this._gate_vm, handler);
        }
        return this.proxy_gate_vm
    }
}
export class GateView extends ViewComponent {

    private ps_lable: Label
    private gold_lable: Label
    private diamond_lable: Label
    private last_battle_lable: Label


    protected onLoad(): void {
        this.ps_lable = this.node.getChildByName('top').getChildByName('value').getComponent(Label)
        this.gold_lable = this.node.getChildByName('top').getChildByName('gold').getChildByName('value').getComponent(Label)
        this.diamond_lable = this.node.getChildByName('top').getChildByName('diamond').getChildByName('value').getComponent(Label)
        this.last_battle_lable = this.node.getChildByName('bottom').getChildByName('curBattleIdText').getComponent(Label)
    }


    get vmHandler() {
        const that = this
        return {
            set(obj: IGateVM_JCQ, prop, value) {
                // 如果原先的值一样就不做视图层的修改了
                if (prop == 'ps' && value != obj[prop]) {
                    that.ps_lable.string = value + '/3'
                }
                if (prop == 'gold') {
                    that.gold_lable.string = value
                }
                if (prop == 'diamond') {
                    that.diamond_lable.string = value
                }
                if (prop == 'last_battle_id') {
                    that.last_battle_lable.string = '当前第' + value + '关'
                }
                obj[prop] = value;
                return true
            }
        };
    }
}

    
export class xhgame {

    .....

    /** 当前游戏用到的视图绑定 */
    static get vm() {
        return gameInstance.game.getVM().getVMs()
    }

    ....
}

使用时只需要 

xhgame.vm.gateVM.gold = 200

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Data Mining数据挖掘—2. Classification分类

3. Classification Given a collection of records (training set) – each record contains a set of attributes – one of the attributes is the class (label) that should be predicted Find a model for class attribute as a function of the values of other attribu…

vuepress-----14、保护私密信息

秘钥存储文件 使用秘钥 忽略提交

通过异步序列化提高图表性能 Diagramming for WPF

通过异步序列化提高图表性能 2023 年 12 月 6 日 MindFusion.Diagramming for WPF 4.0.0 添加了异步加载和保存文件的功能,从而提高了响应能力。 MindFusion.Diagramming for WPF 提供了一个全面的工具集,用于创建各种图表,包括组织结构图、图…

『PyTorch学习笔记』如何快速下载huggingface模型/数据—全方法总结

如何快速下载huggingface模型/数据—全方法总结 文章目录 一. 如何快速下载huggingface大模型1.1. IDM(Windows)下载安装连接1.2. 推荐 huggingface 镜像站1.3. 管理huggingface_hub cache-system(缓存系统) 二. 参考文献 一. 如何快速下载huggingface大模型 推荐 huggingface…

苹果mac电脑如何彻底删除卸载软件?

在苹果电脑上安装和使用软件非常容易,但是卸载软件却可能会变得复杂和困难。不像在Windows上,你不能简单地在控制面板中找到已安装的程序并卸载它们。因此,在这篇文章中,我们将讨论苹果电脑怎么彻底删除软件。 CleanMyMac X全新版…

通信线缆是什么

通信线缆 电子元器件百科 文章目录 通信线缆前言一、通信线缆是什么二、通信线缆的类别三、通信线缆应用实例四、通信线缆的作用原理总结前言 每种线缆都有其特定的特性和用途。通信线缆起到连接和传输信号的作用,是实现通信和数据传输的重要组成部分。 一、通信线缆是什么 …

高级搜索——ST表,离线RMQ问题

文章目录 前言可重复贡献问题ST表的定义ST表的存储结构ST表的预处理预处理的实现 ST表的区间查询对于k的获取区间查询的实现 OJ链接 前言 对于查询区间最值的方法,我们常用的就是线段树,树状数组,单调队列,而树状数组更适合用于快…

AI报告专题:创造性和生成式人工智能

今天分享的AI系列深度研究报告:《AI报告专题:创造性和生成式人工智能》。 (报告出品方:Capgemini) 报告共计:64页 AI一代 生成式人工智能 (AI)正在迅速改变我们与技术的交互方式,使机器能够创…

Java实现屏幕截图程序(一)

在Java中,可以使用Robot类来实现屏幕截图程序。Robot类提供了一组用于生成输入事件和控制鼠标和键盘的方法。 Java实现屏幕截图的步骤如下: 导入Robot类 import java.awt.Robot;创建Robot对象 Robot robot new Robot();获取屏幕分辨率信息 Dimensi…

redis-学习笔记(hash)

Redis 自身已经是 键值对 结构了 Redis 自身的键值对就是通过 哈希 的方式来组织的 把 key 这一层组织完成后, 到了 value 这一层, 还可以用 哈希类型 来组织 (简单的说就是哈希里面套哈希 [数组里面套数组 -> 二维数组] ) [ field value ] hset key field value [ field va…

urllib 异常、cookie、handler及代理(四)

目录 一、urllib异常 二、urllib cookie登录 三、urllib handler 处理器的基本使用 四、urllib 代理和代理池 参考 一、urllib异常 URLError/HTTPError 简介: 1.HTTPError类是URLError类的子类 2.导入的包urllib.error.HTTPError urllib.error.URLError 3.h…

如何将idea中导入的文件夹中的项目识别为maven项目

问题描述 大家经常遇到导入某个文件夹的时候,需要将某个子文件夹识别为maven项目 解决方案

XUbuntu22.04之8款免费UML工具(一百九十七)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…

【计算机组成体系结构】SRAM和DRAM

RAM — Random Access Memory 随机访问存储器 —指定某一存储单元地址的时候,存储单元的读取速度并不会因为存储单元的物理位置改变 SRAM即为 Static RAM 静态随机访问存储器 — 用于主存DRAM即为 Dynamic RAM 动态随机访问存储器 — 用于Cache 一、SRAM和DRAM的特…

oomall课堂笔记

一、项目分层结构介绍 controller层(控制器层): 作用:负责输出和输入,接收前端数据,把结果返回给前端。 1.处理用户请求,接收用户参数 2.调用service层处理业务,返回响应 servi…

Javaweb之Maven仓库的详细解析

2.3 Maven仓库 仓库:用于存储资源,管理各种jar包 仓库的本质就是一个目录(文件夹),这个目录被用来存储开发中所有依赖(就是jar包)和插件 Maven仓库分为: 本地仓库:自己计算机上的一个目录(用来存储jar包) 中央仓库&a…

利用R语言heatmap.2函数进行聚类并画热图

数据聚类然后展示聚类热图是生物信息中组学数据分析的常用方法,在R语言中有很多函数可以实现,譬如heatmap,kmeans等,除此外还有一个用得比较多的就是heatmap.2。最近在网上看到一个笔记文章关于《一步一步学heatmap.2函数》,在此与…

python 涉及opencv mediapipe知识,眨眼计数 供初学者参考

基本思路 我们知道正面侦测到人脸时,任意一只眼睛水平方向上的两个特征点构成水平距离,上下两个特征点构成垂直距离 当头像靠近或者远离摄像头时,垂直距离与水平距离的比值基本恒定 根据这一思路 当闭眼时 垂直距离变小 比值固定小于某一个…

主动而非被动:确保网络安全运营弹性的途径

金融部门处理威胁的经验对网络安全领域的任何人都有启发——没有什么可以替代提前摆脱潜在的风险和问题。 从狂野西部的银行劫匪到勒索软件即服务 (RaaS),全球金融生态系统面临的威胁多年来发生了巨大变化。技术进步带动了金融业的快速发展,从现金交易到…

【开放集检测OSR】open-set recognition(OSR)开集识别概念辨析

开放集学习 Openset Learning 主动学习 Active Learning 例外检测 Out-of-Distribution open-set recognition(OSR)开集识别 anomaly detection和outlier detection 文章目录 OOD检测OSR开放集识别OSR开放集识别在训练和测试阶段的数据集使用数据分布似然函数OSR开放集识别的特…