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;
    }
    @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

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

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

相关文章

【go从入门到精通】go包,内置类型和初始化顺序

大家好&#xff0c;这是我给大家准备的新的一期专栏&#xff0c;专门讲golang&#xff0c;从入门到精通各种框架和中间件&#xff0c;工具类库&#xff0c;希望对go有兴趣的同学可以订阅此专栏。 go基础 。 Go文件名&#xff1a; 所有的go源码都是以 ".go" 结尾&…

pytorch -- torch.nn网络结构

1. 官网描述 官网 使用 torch.nn 模块&#xff0c;我们可以创建自定义的神经网络模型&#xff0c;并使用 PyTorch 提供的优化器&#xff08;如 torch.optim&#xff09;和损失函数来训练和优化模型。 2. 常见结构 1.卷积操作 定义&#xff1a; 二维卷积 1.1版本 nn.functio…

香港大学发布思维扩散DoT,让思维在时间上扩散,提效保质!

引言&#xff1a;探索结合扩散模型与思维链来提升大模型推理能力 在人工智能领域&#xff0c;大语言模型&#xff08;LLMs&#xff09;已经引起了广泛的关注&#xff0c;它们在自然语言处理和机器学习的经典问题上展现出了显著的推理能力。特别是&#xff0c;思维链&#xff0…

Vue开发实例(九)动态路由实现左侧菜单导航

之前在【Vue开发实例&#xff08;六&#xff09;实现左侧菜单导航】文中实现了菜单的导航&#xff0c;本篇是在那个基础上改造的。 动态路由实现左侧菜单导航 一、动态菜单创建二、根据菜单数据来创建路由三、添加路由已加载标记&#xff0c;省的每次点击菜单都要加载 一、动态…

开源项目:图像分类算法在保险行业的创新应用与实践

一、引言 在当今数字化时代&#xff0c;保险行业正经历着前所未有的变革。传统保险公司面临着新兴科技的挑战&#xff0c;被迫重新思考其业务模式和营销策略。在这种背景下&#xff0c;我有幸参与了一个项目&#xff0c;该项目旨在通过整合多种销售渠道和技术手段&#xff0c;提…

【蓝桥杯】错误票据

今天是2024年3月1号&#xff0c;蓝桥杯比赛还有一个月的时间&#xff0c;虽说自己不指望拿奖吧&#xff0c;但是还是有些莫i名的焦虑&#xff0c;这道题目都做不出来&#xff0c;感觉自己真的有点菜啊&#xff01;但是还好啦&#xff0c;我觉得是因为我没有题感&#xff0c;慢慢…

DDS数据分发服务——提升汽车领域数据传输效率

1.引言 随着智能化技术的快速发展&#xff0c;汽车行业正经历着一场革命性的变革。如今的分布式系统变得越来越复杂且庞大&#xff0c;对网络通信基数要求在功能和性能层面越来越高。数据分发服务&#xff08;DDS&#xff09;作为一项先进的数据传输解决方案&#xff0c;在汽车…

Redis-基础篇

Redis是一个开源、高性能、内存键值存储数据库&#xff0c;由 Salvatore Sanfilippo&#xff08;网名antirez&#xff09;创建&#xff0c;并在BSD许可下发布。它不仅可以用作缓存系统来加速数据访问&#xff0c;还可以作为持久化的主数据存储系统或消息中间件使用。Redis因其数…

【大数据架构(3)】Lambda vs. Kappa Architecture-选择你需要的架构

文章目录 一. Data Processing Architectures1. Lambda Architecture1.1. 架构说明a. Data Ingestion Layerb. Batch Layer (Batch processing)c. Speed Layer (Real-Time Data Processing)d. Serving Layer 1.2. Lambda Architecture的优缺点1.3. 使用案例 2. Kappa Architect…

数据分析-Pandas数据的探查面积图

数据分析-Pandas数据的探查面积图 数据分析和处理中&#xff0c;难免会遇到各种数据&#xff0c;那么数据呈现怎样的规律呢&#xff1f;不管金融数据&#xff0c;风控数据&#xff0c;营销数据等等&#xff0c;莫不如此。如何通过图示展示数据的规律&#xff1f; 数据表&…

MyBatis 面试题

什么是MyBatis&#xff1f; MyBatis 是一个开源、轻量级的数据持久化框架&#xff0c;是 JDBC 和 Hibernate 的替代方案。MyBatis 内部封装了 JDBC&#xff0c;简化了加载驱动、创建连接、创建 statement 等繁杂的过程&#xff0c;开发者只需要关注 SQL 语句本身。 MyBatis 支…

静态时序分析:SDC约束命令set_case_analysis详解

相关阅读 静态时序分析https://blog.csdn.net/weixin_45791458/category_12567571.html?spm1001.2014.3001.5482 目录 指定值 指定端口/引脚列表 简单使用 set_case_analysis命令用于对电路进行特定模式的设定&#xff0c;例如对于一个工作在正常模式下的芯片&#xff0c;…

08 yum和git

什么是软件包 安装软件&#xff0c;一个通常的办法就是下载程序的源代码进行编译。这种太麻烦&#xff0c;于是一些人把常用软件编译好&#xff0c;做成软件包放在服务器上&#xff0c;通过包管理器可以很方便的得到这个软件包安装&#xff0c;就好比手机上的应用商店 yum&am…

美梦从舒适开始,康姿百德床垫为睡眠健康护航

在当今社会&#xff0c;高质量的睡眠已成为人们对生活品质的追求&#xff0c;对床垫的选择也变得越来越讲究。在我们繁忙的生活中&#xff0c;一张优质的床垫不仅是我们舒适休息的保障&#xff0c;更是保持健康生活方式的重要部分。康姿百德床垫&#xff0c;作为市场上的佼佼者…

14-Linux部署Hadoop集群

Linux部署Hadoop集群 简介 1&#xff09;Hadoop是一个由Apache基金会所开发的分布式系统基础架构。 2&#xff09;主要解决&#xff0c;海量数据的存储和海量数据的分析计算问题。 Hadoop HDFS 提供分布式海量数据存储能力 Hadoop YARN 提供分布式集群资源管理能力 Hadoop…

R语言使用dietaryindex包计算NHANES数据多种健康饮食指数 (HEI等)(1)

健康饮食指数 (HEI) 是评估一组食物是否符合美国人膳食指南 (DGA) 的指标。Dietindex包提供用户友好的简化方法&#xff0c;将饮食摄入数据标准化为基于指数的饮食模式&#xff0c;从而能够评估流行病学和临床研究中对这些模式的遵守情况&#xff0c;从而促进精准营养。 该软件…

【C++】string 类 ( 上)

标准库中的string类 注意&#xff1a; 1. string是表示字符串的字符串类 2. 该类的接口与常规容器的接口基本相同&#xff0c;再添加了一些专门用来操作string的常规操作。 比特就业课 3. string在底层实际是&#xff1a;basic_string模板类的别名&#xff0c;typedef basi…

RFID(Radio Frequency Identification)技术笔记

一、RFID的介绍 RFID&#xff0c;全称为Radio Frequency Identification&#xff0c;即射频识别技术&#xff0c;也常被称为电子标签或无线射频识别。它是一种非接触式的自动识别技术&#xff0c;通过射频信号自动识别目标对象并获取相关数据&#xff0c;识别过程无需人工干预&…

LeetCode 刷题 [C++] 第45题.跳跃游戏 II

题目描述 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] 处&#xff0c;你可以跳转到任意 nums[i j] 处: 0 < j < nums[i]i j < n 返回到达 nums[n …

金融行业专题|期货超融合架构转型与场景探索合集(2023版)

更新内容&#xff1a; 更新 SmartX 超融合在期货行业的覆盖范围、部署规模与应用场景。新增 CTP 主席系统实践与评测、容器云资源池等场景实践。更多超融合金融核心生产业务场景实践&#xff0c;欢迎下载阅读电子书《SmartX 金融核心生产业务场景探索文章合集》。 面对不断变…