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

news2024/10/1 19:39:54

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;
    }
    @Override
    public 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 property
            int 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_VALUE
                    h = 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.coloradmin.cn/o/1484761.html

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

相关文章

抖音视频评论数据挖掘软件|视频批量下载工具

这款基于C#开发的抖音视频评论数据挖掘软件是一款功能强大、易于使用的工具。它不仅支持通过关键词进行搜索抓取&#xff0c;还能够通过分享链接进行单个视频的抓取和下载。主要功能模块如下&#xff1a; 批量视频提取 操作模块&#xff1a;用户可以输入要搜索的关键词&#…

python:pyecharts 画基金净值 月K线图

pip install pyecharts1.9.1 pyecharts-1.9.1-py3-none-any.whl 我想在本地&#xff08;PC) 画出 基金净值 月K线图&#xff0c;不想每次看图都需联网。 cd my_dir mkdir echarts cd echarts curl -O https://assets.pyecharts.org/assets/echarts.min.js 修改一下开源代码 …

【飞桨EasyDL】飞桨EasyDL发布的模型转换onnx(附工程代码)

一个愿意伫立在巨人肩膀上的农民...... 一、paddle转onnx转rknn环境搭建 paddle转onnx和onnx转rknn两个环境可以分开搭建&#xff0c;也可以搭建在一起。这里选择分开搭建&#xff0c;先搭建paddle转onnx。 1.1、创建环境 选择python3.8.13包进行创建环境 conda create --nam…

Ubuntu22.04下在Spark2.4.0中采用Local模式配置并启动pyspark

目录 一、前言 二、版本信息 三、配置相关文件 1.修改spark-env.sh文件 2.修改.bashrc文件 四、安装Python3.5.2并更改默认Python版本 1.查看当前默认Python版本 2.安装Python3.5.2 2.1 下载Python源码 2.2 解压源码 2.3 配置安装路径 2.4 编译和安装 2.5 验证安装…

走进SQL审计视图——《OceanBase诊断系列》之二

1. 前言 在SQL性能诊断上&#xff0c;OceanBase有一个非常实用的功能 —— SQL审计视图(gv$sql_audit)。在OceanBase 4.0.0及更高版本中&#xff0c;该功能是 gv$ob_sql_audit。它可以使开发和运维人员更方便地排查在OceanBase上运行过的任意一条SQL&#xff0c;无论这些SQL是成…

最近半年博客产出的反思

最近完善boss资料的时候&#xff0c;我认为自己在大学期间学习过程中经常用博客记录学习内容以及在学习过程中写博客笔记是个不错的好习惯&#xff0c;在询问了师傅的意见之后决定把CSDN的主页也挂上去。 非常荣幸平台上今天有一位老师看见我的简历之后主动和我交流。对我的博客…

Sora来袭!机器人+Sora落地性如何?

2022年底&#xff0c;OpenAI正式推出ChatGPT&#xff0c;这款由人工智能技术驱动的自然语言处理工具能够通过学习和理解人类的语言来进行对话 。ChatGPT是OpenAI迈出的第一步&#xff0c;这款让所有人都能体会到人工智能潜力的现象级产品&#xff0c;展现出了文字对于过去人工智…

Xcode15与苹果ios17适配以及遇到的问题

大家好&#xff0c;我是你们的好朋友咕噜铁蛋&#xff01;最近&#xff0c;苹果发布了全新的iOS17系统&#xff0c;而作为开发者&#xff0c;我们需要确保我们的应用程序能够与这个新系统完美适配。因此&#xff0c;今天我将和大家分享一些关于Xcode15与苹果17系统适配的经验&a…

手写 Attention 迷你LLaMa2——LLM实战

https://github.com/Yuezhengrong/Implement-Attention-TinyLLaMa-from-scratch 1. Attention 1.1 Attention 灵魂10问 你怎么理解Attention&#xff1f; Scaled Dot-Product Attention中的Scaled&#xff1a; 1 d k \frac{1}{\sqrt{d_k}} dk​ ​1​ 的目的是调节内积&…

Parallel Computing - 一文讲懂并行计算

目录 Throughput/LatencySerial ComputingParallel ComputingTypes of parallel computersSimple 4-width SIMDAmdahls lawTypes of parallelism**Data Parallel Model**Task parallel PartitioningDomain DecompositionFunctional Decomposition CommunicationsExample that d…

Android 基础入门 基础简介

1. 观察App运行日志 2.Android 开发设计的编程语言 koltin Java c c 3.工程目录结构 4.Gradle 5.build.gradle 文件解析 plugins {id("com.android.application")//用了哪些插件 主配置文件版本控制 所以这里不用写版本 }android {namespace "com.tiger.myap…

unity学习(44)——选择角色菜单——顺利收到服务器的数据

本节的思路参考自&#xff0c;内容并不相同&#xff1a;13ARPG网络游戏编程实践&#xff08;十三&#xff09;&#xff1a;角色选择UI及创建面板制作&#xff08;四&#xff09;_哔哩哔哩_bilibili 现在的代码写在MessageManager.cs中&#xff0c;函数名UserHandler(是从OnMess…

mongodb 图形界面工具 -- Studio 3T(下载、安装、连接mongodb数据库)

目录 mongodb 图形界面工具 -- Studio 3T下载安装第一次使用&#xff1a;注册添加一个连接&#xff08;连接 mongodb 数据库&#xff09;1、点击【添加新连接】&#xff0c;选择【手动配置我的连接设置】2、对 Server 设置连接数据3、连接的用户认证设置&#xff08;创建数据库…

【系统分析师】-需求工程

一、需求工程 需求工程分为需求开发和需求管理。 需求开发&#xff1a;需求获取&#xff0c;需求分析&#xff0c;需求定义、需求验证。 需求管理&#xff1a;变更控制、版本控制、需求跟踪&#xff0c;需求状态跟踪。&#xff08;对需求基线的管理&#xff09; 1.1需求获取…

BUGKU 网站被黑

打开环境&#xff0c;什么都没发现&#xff0c;使用蚁剑扫描一下&#xff0c;发现shell.php&#xff0c;打开 使用BP抓包&#xff0c;进行爆破 得到密码&#xff1a;hack 进去得到flag

【python】1.python3.12.2和pycharm社区版的安装指南

欢迎来CILMY23的博客喔&#xff0c;本篇为【python】1.python3.12.2和pycharm社区版的安装指南&#xff0c;感谢观看&#xff0c;支持的可以给个一键三连&#xff0c;点赞关注收藏。 目录 一、python3.12.2的下载与安装 1.1下载 1.2安装 二、pycharm的安装 2.1下载安装 2…

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

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

Redis持久化+Redis内存管理和优化+Redis三大缓存问题

Redis持久化Redis内存管理和优化Redis三大缓存问题一、Redis高可用二、Redis持久化1、RDB持久化1.1 触发条件(1) 手动触发(2) 自动触发(3) 其他自动触发机制 1.2 执行流程1.3 启动时加载 2、AOF持久化2.1 开启AOF2.2 执行流程(1) 命令追加(append)(2) 文件写入(write)和文件同步…

Leetcode630. 课程表 III

Every day a Leetcode 题目来源&#xff1a;630. 课程表 III 解法1&#xff1a;反悔贪心 经验告诉我们&#xff0c;在准备期末考试的时候&#xff0c;先考的课程先准备。同理&#xff0c;lastDay 越早的课程&#xff0c;应当越早上完。但是&#xff0c;有的课程 duration 比…

MATLAB环境下基于图像处理的计算病理学图像分割(MATLAB R2021B)

人工智能是病理学诊断和研究的重要新兴方法&#xff0c;其不仅可用于病理形态数据分析&#xff0c;还可整合免疫组化、分子检测数据和临床信息&#xff0c;得出综合的病理诊断报告&#xff0c;为患者提供预后信息和精准的药物治疗指导。计算病理学是病理学与AI、计算机视觉等信…