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.pswp.cn/news/715614.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/715614.shtml
英文地址,請注明出處:http://en.pswp.cn/news/715614.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Redis基本知識

一、什么是Redis Redis是一種基于內存的數據庫&#xff0c;對數據的讀寫操作都是在內存中完成&#xff0c;因此讀寫速度非常快&#xff0c;用于存儲鍵值對、緩存、消息隊列、分布式鎖等。 二、Redis和mencached的區別 相同&#xff1a;都是基于內存的數據庫&#xff0c;讀寫都…

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…

域名及地址正確外,若依后臺無法正常加載頁面和退出報404問題

寫小程序退出的時候&#xff0c;另外寫了一個自定義退出處理類&#xff0c;里面的響應瀏覽器的代碼每次都走。因為原來也有個退出處理類&#xff0c;所以先后走了2次&#xff0c;因為就出現了問題。 LogoutSuccessHandlerImpl類里的&#xff1a; ServletUtils.renderString(r…

【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…

裴蜀定理(Bézout’s identity)

裴蜀定理&#xff08;Bzout’s identity&#xff09;是一個數論定理&#xff0c;也稱為貝祖等式。它表明&#xff0c;對于任意給定的兩個整數 a a a 和 b b b&#xff0c;存在整數 x x x 和 y y y&#xff0c;使得它們滿足以下方程&#xff1a; a x b y gcd ? ( a , b )…

【簡略知識】項目開發中,VO,BO,PO,DO,DTO究竟是何方妖怪?

前言 在項目開發中&#xff0c;是否需要定義VO&#xff08;視圖對象&#xff09;&#xff0c;BO&#xff08;業務對象&#xff09;&#xff0c;PO&#xff08;持久化對象&#xff09;&#xff0c;DO&#xff08;領域對象&#xff09;&#xff0c;DTO&#xff08;數據傳輸對象&…