17.来自Sora的夺舍妄想——享元模式详解

OpenAI 的 Sora 模型面世之后,可以说人类抵御AI的最后阵地也沦陷了。
在此之前,人们面对AI交互式对话,AI制图,AI建模之类的奇迹时,还可以略微放肆的说:“的确很神奇,这毕竟还是比人类世界低了一个维度,并没有那么可怕。”
而现在,视频生成模型Sora在发展初期创造的视频就几乎可以以假乱真了,这对人类来说究竟意味着什么?
也许大多数人并没有想清楚。
AI可以生成视频,这意味着大模型已经完全理解了人类所在的三维世界的一切物理规则和绝大部分的社会规则。它正在变得比这个世界上的大多数人都更了解这个世界。
在这里插入图片描述

AI创造的视频中的各种“生命体”在现实世界中是不存在的,如果他们有所谓的“意识”真的可以称之为“生命”的话。他们的世界是我们世界的投影,在那个世界里“生活”的“人”其实并不清楚他们的世界是怎么来的,就像现在的我们一样。
就像电影《异次元骇客》所描述的一样,每个世界都是更高一级世界的投影,每个人都是NPC,每当上层世界的玩家“登录”,下层的意识就会被抢占。所以有些人会突然发神经仿佛人格分裂一样,就好比GTA5中的老麦在你打开游戏前是一个好父亲,而在你打开游戏后变成了砍天砍地的恶棍。时不时他还会冒出来一句:“Oh, my goodness, what have I done?!”
在这里插入图片描述
幻想总是能让人思绪飞扬,今天我想从“夺舍”这个角度来讲一讲设计模式中的享元模式。


一言

享元模式,旨在通过共享对象来减少内存使用量并提高性能。它适用于那些由于对象内部状态重复而导致大量内存消耗的场景。


对下一层世界的秩序设计

我们假定你的几行代码就可以设计出一个比你低一个层次的世界,那么你打算如何实现“每个人都是NPC,每当上层世界的玩家登录,下层的意识就会被抢占”这一需求呢?
在这里插入图片描述

核心代码Ctrl CV?

“欸,我直接copy走起”,相信大家第一时间想到的都是这个设计。
在这里插入图片描述
的确是通俗易懂,传统的定制化编程实现,但也确实存在很多的隐患。

分析

几个玩家操控的NPC相似度这么高,如果分多个虚拟空间来处理,相当于一个NPC占用了多个实例,造成了极大的内存浪费。
那么有没有一种可能,我们将这些NPC实例整合到一个NPC中(让他拥有多个人格),对于硬盘、内存、CPU、数据库空间等服务器资源都可以达成共享,是不是就减少了服务器资源的浪费呢?
对于代码而言,我们也后期也只需要维护和扩展一份,这样的思路是不是更好呢?


享元模式

也许乍一听这个名词很多朋友会一愣,觉得自己从未接触过这个设计模式,实际上它非常的常见。比如说数据库连接池的设计,里面都是创建好的连接对象,在这些连接对象中有我们需要的就直接拿来用,没有就创建一个。
在这种思路下,解决了重复对象的内存浪费问题,当系统中存在大量相似对象,需要缓冲池时,不再需要创建新对象,而是直接在缓冲池里拿。
不光是数据库连接池,String 常量池 ,缓冲池等等都是享元模式的应用,也是池技术的重要实现方式。

设计

在这里插入图片描述

  1. FlyWeight 是抽象的享元角色,它是产品的抽象类,同时定义出对象的外部状态和内部状态的接口或实现;
  2. ConcreteFlyWeight 是具体的享元角色,是具体的产品类,实现抽象角色自定义相关业务;
  3. UnsharedConcreteFlyWeight 是不可共享的角色,一般不会出现在享元工厂中;
  4. FlyWeightFactory 享元工厂类,用于构建一个池容器(集合),同时提供从池中获取对象的方法;

内部状态与外部状态

享元模式有两个要求:细粒度和共享对象。这里就涉及到内部状态和外部状态了。那么什么是内部状态和外部状态呢?
通俗的讲,大家都玩过王者荣耀或者英雄联盟这类的MOBA游戏,召唤师峡谷的地图信息和地图资源是基本固定的,而每局游戏参战的英雄,英雄的位置、状态、技能等信息则是千变万化的。在这个例子中:

  • 地图是内部状态,地图上野怪的属性和状态是外部状态
  • 英雄模型是内部状态,英雄的血量、等级等变化的是外部状态

内部状态指对象共享出来的信息,存储在享元对象内部且不会随环境的改变而改变。外部状态指对象得以依赖的一个标记,是随环境改变而改变的、不可共享的状态。
可以试想以下,如果不采用享元模式,类似的游戏(PUBG、棋牌类游戏等)每一局都构建一整套资源有多么恐怖。

代码实现

现在我们开始编辑对NPC人格的入侵程序:
玩家

public class User {private String name;public User(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

NPC

public abstract class NPC {public abstract void use(User user);//抽象方法
}

NPC享元角色

public class ConcreteNPC extends NPC{private String type = "";public ConcreteNPC(String type) {this.type = type;}@Overridepublic void use(User user) {System.out.println("NPC的人格切换为:"+type+",在使用中..  使用者为:"+user.getName());}
}

NPC享元工厂

public class NPCFactory {private HashMap<String,ConcreteNPC> pool = new HashMap<>();public NPC getNpcCategory(String type){if (!pool.containsKey(type)){pool.put(type,new ConcreteNPC(type));}return (NPC) pool.get(type);}public int getNpcCount(){return pool.size();}
}

客户端

public class Client {public static void main(String[] args) {NPCFactory factory = new NPCFactory();NPC npc1 = factory.getNpcCategory("圣人");npc1.use(new User("Tom"));NPC npc2 = factory.getNpcCategory("狂徒");npc2.use(new User("Jack"));NPC npc3 = factory.getNpcCategory("学者");npc3.use(new User("Linda"));NPC npc4 = factory.getNpcCategory("学者");npc4.use(new User("Lucy"));NPC npc5 = factory.getNpcCategory("学者");npc5.use(new User("Amanda"));System.out.println("NPC人格分类共:"+factory.getNpcCount());}
}

执行

在这里插入图片描述
可以看到,在当前的设计下,NPC的人格集中管理在享元工厂的池子中,当有新的玩家注入新的人格则会扩充这个池子的容量,如果没有新的人格加入,则会从池子中提取已有的人格注入到NPC体内。


享元模式在JDK-Integer源码中的应用

之前网上有这样一种论调:“国内IT行业程序员的面试已经越来越朝向八股化发展了。
面试造火箭,工作打螺丝”。
从某种角度来看,似乎说的是行业面试的现状。但从编程基础的角度考虑,有些八股本身不是问题,问题是很多朋友没有真正理解八股描述的底层原理,全靠死记硬背。
比如说下面这个面试题:

		Integer a = Integer.valueOf(127);Integer b = new Integer(127);Integer c = Integer.valueOf(127);Integer d = new Integer(127);System.out.println(a.equals(b));System.out.println(a==b);System.out.println(a==c);System.out.println(d==a);System.out.println(d==b);

八股文只会告诉你,上面的结果是:
在这里插入图片描述
但我觉得这不是我们要去背的东西,我们要理解为什么是这样的结果。这个结果其实就源自Integer的享元模式,我们先看下源码。
相关源码片

/*** Cache to support the object identity semantics of autoboxing for values between* -128 and 127 (inclusive) as required by JLS.** The cache is initialized on first usage.  The size of the cache* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.* During VM initialization, java.lang.Integer.IntegerCache.high property* may be set and saved in the private system properties in the* sun.misc.VM class.*/private static class IntegerCache {static final int low = -128;static final int high;static final Integer cache[];static {// high value may be configured by propertyint h = 127;String integerCacheHighPropValue =sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");if (integerCacheHighPropValue != null) {try {int i = parseInt(integerCacheHighPropValue);i = Math.max(i, 127);// Maximum array size is Integer.MAX_VALUEh = Math.min(i, Integer.MAX_VALUE - (-low) -1);} catch( NumberFormatException nfe) {// If the property cannot be parsed into an int, ignore it.}}high = h;cache = new Integer[(high - low) + 1];int j = low;for(int k = 0; k < cache.length; k++)cache[k] = new Integer(j++);// range [-128, 127] must be interned (JLS7 5.1.7)assert IntegerCache.high >= 127;}private IntegerCache() {}}/*** Returns an {@code Integer} instance representing the specified* {@code int} value.  If a new {@code Integer} instance is not* required, this method should generally be used in preference to* the constructor {@link #Integer(int)}, as this method is likely* to yield significantly better space and time performance by* caching frequently requested values.** This method will always cache values in the range -128 to 127,* inclusive, and may cache other values outside of this range.** @param  i an {@code int} value.* @return an {@code Integer} instance representing {@code i}.* @since  1.5*/public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}

源码分析

  1. 在valueOf方法中,先判断值是否在IntegerCache中,如果不在,就创建新的Integer(new),否则,就直接从缓存池返回;
  2. valueOf方法就使用到了享元模式;
  3. 如果使用valueOf方法得到一个Integer实例范围在-128~127之间,执行速度比 new 快;

所以,以-128~127为界,比较Integer是否是同一个对象时会有不同的表现结果。


“享”即共享,“元”即对象,如果系统中有大量对象占用缓存,并且对象状态大都可以外部化时,我们就可以考虑选用享元模式。
但是也要清楚的看到,享元模式在提高了效率的同时也提高了系统复杂度,而且,外部状态具有固化特性不会随着内部状态的改变而改变,这也会在一定程度上增加编码逻辑的理解难度。


关注我,共同进步,每周至少一更。——Wayne

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

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

相关文章

2024年腾讯云部署幻兽帕鲁服务器,如何选择合适的服务器配置套餐畅玩游戏?

选择合适的服务器配置套餐以畅玩《幻兽帕鲁》游戏&#xff0c;首先需要考虑的是玩家数量和对服务器性能的需求。根据腾讯云提供的配置推荐&#xff0c;对于4到8人的玩家&#xff0c;推荐配置为4核16G12M&#xff1b;而10到20人的玩家则建议选择8核32G22M配置。这是因为《幻兽帕…

小程序页面指定区域局部滚动,做上拉和触底刷新

业务需求&#xff1a;在页面某个固定区域滑动 思路&#xff1a;滑动高度 页面高度 - 自定义导航高度&#xff08;不是自己自定义的导航可以省略&#xff09;- 按钮高度 - 单词数高度 实现 &#xff1a; 1.数据展示区内使用scroll-view&#xff0c;设置y轴滚动&#xff08;…

swoole

php是单线程。php是靠多进程来处理任务&#xff0c;任何后端语言都可以采用多进程处理方式。如我们常用的php-fpm进程管理器。线程与协程,大小的关系是进程>线程>协程,而我们所说的swoole让php实现了多线程,其实在这里来说,就是好比让php创建了多个进程,每个进程执行一条…

初阶数据结构:二叉树

目录 1. 树的相关概念1.1 简述&#xff1a;树1.2 树的概念补充 2. 二叉树2.1 二叉树的概念2.2 二叉树的性质2.3 二叉树的存储结构与堆2.3.1 存储结构2.3.2 堆的概念2.3.3 堆的实现2.3.3.1 堆的向上调整法2.3.3.2 堆的向下调整算法2.3.3.3 堆的实现 1. 树的相关概念 1.1 简述&a…

【C++ AVL树】

文章目录 AVL树AVL树的概念AVL树节点的定义AVL树的插入AVL树的旋转右单旋左单旋左右双旋右左双旋 代码实现 总结 AVL树 AVL树的概念 二叉搜索树在顺序有序或接近有序的情况下&#xff0c;而插入搜索树将退化为单叉树&#xff0c;此时查找的时间复杂度为O(n)&#xff0c;效率低…

鸿蒙Harmony应用开发—ArkTS声明式开发(通用属性:颜色渐变)

设置组件的颜色渐变效果。 说明&#xff1a; 从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 linearGradient linearGradient(value: { angle?: number | string; direction?: GradientDirection; colors: Array; repea…

mamba-ssm安装building wheel卡着不动后error...避坑解决方法

文章目录 方法1、下载whl文件到本地后pip install安装成功后验证&#xff1a; 方法2、拉取Docker镜像 对于项目中用到MambaIR的小伙伴&#xff0c;需要pip安装 causal_conv1d和 mamba-ssm两个包及其依赖&#xff1a; torch packing transformersMambaIR-Github主页&#xff0…

【C++】vector的使用及其模拟实现

这里写目录标题 一、vector的介绍及使用1. vector的介绍2. 构造函数3. 遍历方式4. 容量操作及空间增长问题5. 增删查改6. vector二维数组 二、vector的模拟实现1. 构造函数2. 迭代器和基本接口3. reserve和resize4. push_back和pop_back5. insert和erase5. 迭代器失效问题5. 浅…

【Java】基础算法练习题

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 目录 基础算法练习题&#x1f680;1. 两数之和…

Django 管网项目 三

Django 官网文档 ​​Writing your first Django app, part 2 | Django documentation | Django 本文内容涉及创建视图 View&#xff0c;路由&#xff0c;和模版。并对内容进行渲染。 创建视图 在我们的投票应用中&#xff0c;我们需要下列几个视图&#xff1a; 问题索引页—…

ChatGPT支持下的PyTorch机器学习与深度学习技术应用

近年来&#xff0c;随着AlphaGo、无人驾驶汽车、医学影像智慧辅助诊疗、ImageNet竞赛等热点事件的发生&#xff0c;人工智能迎来了新一轮的发展浪潮。尤其是深度学习技术&#xff0c;在许多行业都取得了颠覆性的成果。另外&#xff0c;近年来&#xff0c;Pytorch深度学习框架受…

相关知识1111

一、 店铺编号和相关负责人 1、天猫兄弟、锦格 京东凡越 福林哥 如萍姐 2、京东锦格 天猫凡越 林森 雷佳华 3、天猫从简 京东从简 孔哥 4、抖音锦格 拼多多凡越 鸿哥 不知道哪个店铺编号&#xff1a;0 二、天猫京东聊天界面快捷搜索商品 1、 天猫只能根据标题搜索 2、京东是…

神经网络之万能定理python-pytorch实现,可以拟合任意曲线

神经网络之万能定理python-pytorch实现&#xff0c;可以拟合任意曲线 博主&#xff0c;这几天一直在做这个曲线拟合的实验&#xff0c;讲道理&#xff0c;网上可能也有很多这方面的资料&#xff0c;但是博主其实试了很多&#xff0c;效果只能对一般的曲线还行&#xff0c;稍微…

java之抽象类

什么是抽象类&#xff1f; 抽象就是不能具体化&#xff0c;不能实例化 作为父类&#xff0c;让子类去实现 abstract修饰类就是抽象类 abstract修饰方法就是抽象方法修饰符 abstract class 类名{修饰符 abstract 返回值类型 方法名(形参列表); }public abstract class A {//不…

CTFHUB--文件包含漏洞--RCE

文件包含漏洞 文件包含漏洞也是一种注入型漏洞&#xff0c;其本质就是输入一段用户能够控制的脚本或者代码&#xff0c;并让服务端执行。有时候由于网站功能需求&#xff0c;会让前端用户选择要包含的文件&#xff0c;而开发人员又没有对要包含的文件进行安全考虑&#xff0c;…

CSS【详解】居中对齐 (水平居中 vs 垂直居中)

水平居中 内部块级元素的宽度要小于容器(父元素) 方案一&#xff1a;文本居中对齐&#xff08;内联元素&#xff09; 限制条件&#xff1a;仅用于内联元素 display:inline 和 display: inline-block; 给容器添加样式 text-align:center<!DOCTYPE html> <html lang&q…

【简略知识】项目开发中,VO,BO,PO,DO,DTO究竟是何方妖怪?

前言 在项目开发中&#xff0c;是否需要定义VO&#xff08;视图对象&#xff09;&#xff0c;BO&#xff08;业务对象&#xff09;&#xff0c;PO&#xff08;持久化对象&#xff09;&#xff0c;DO&#xff08;领域对象&#xff09;&#xff0c;DTO&#xff08;数据传输对象&…

笨办法学 Python3 第五版(预览)(三)

原文&#xff1a;Learn Python the Hard Way, 5th Edition (Early Release) 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 练习 30&#xff1a;假如 这是你将要输入的下一个 Python 脚本&#xff0c;它向你介绍了if语句。输入这个代码&#xff0c;确保它能够完美运行…

Home-credit海外贷款信贷产品源码/线上贷款产品大全/贷款平台软件源码/海外借贷平台

测试环境&#xff1a;Linux系统CentOS7.6、宝塔、PHP7.3、MySQL5.6&#xff0c;根目录public&#xff0c;伪静态laravel5&#xff0c;开启ssl证书 语言&#xff1a;中文简体、英文 laravel框架的程序有点多&#xff0c;这个团队估计主要就是搞laravel开发的&#xff0c;基本上…

YOLOv9独家原创改进|增加SPD-Conv无卷积步长或池化:用于低分辨率图像和小物体的新 CNN 模块

专栏介绍&#xff1a;YOLOv9改进系列 | 包含深度学习最新创新&#xff0c;主力高效涨点&#xff01;&#xff01;&#xff01; 一、文章摘要 卷积神经网络(CNNs)在计算即使觉任务中如图像分类和目标检测等取得了显著的成功。然而&#xff0c;当图像分辨率较低或物体较小时&…