設計模式十二:享元模式(Flyweight Pattern)

當我們需要創建大量相似對象時,享元模式可以幫助我們節省內存空間和提高性能。該模式通過共享相同的數據來減少對象的數量。
在享元模式中,有兩種類型的對象:享元(Flyweight)和非享元(Unshared Flyweight)。享元對象是可共享的,它包含內部狀態和外部狀態。內部狀態是不變的,它可以在多個對象之間共享。外部狀態是會變化的,它由客戶端代碼傳遞給享元對象,因此它不能被共享。
享元模式的核心思想是將相同的外部狀態提取出來作為共享對象,在使用時通過傳遞外部狀態進行對象的定制。這樣就可以避免創建大量相同的對象,從而減少內存占用。

享元模式的適用場景

享元模式適用于需要創建大量相似對象,并希望節省內存空間和提高性能的場景。它通過共享相同的狀態來減少對象的數量,以達到優化性能的目的。

  1. 當一個類有大量的相似對象,且這些對象可以共享一些相同的狀態時,可以考慮使用享元模式。通過共享相同的狀態,可以減少對象的數量,節省內存空間。
  2. 當大量對象導致內存占用過高,而且這些對象的狀態可以被外部化時,可以使用享元模式來共享這些外部狀態。外部狀態可以由客戶端代碼傳遞給享元對象,從而避免創建大量重復的對象。
  3. 當需要在多個對象之間共享和復用狀態時,可以使用享元模式。通過共享狀態,可以實現對象的復用,提高性能。
  4. 當對象的數量很大,但每個對象只包含少量的狀態時,可以考慮使用享元模式。通過共享狀態,可以減少對象的數量,降低系統的復雜性和維護成本。
  5. 當希望將對象的內部狀態和外部狀態分離,并通過外部狀態對對象進行定制時,可以使用享元模式。內部狀態是不變的,可以在多個對象之間共享,而外部狀態會變化,可以通過客戶端代碼傳遞給享元對象。

享元模式主要包含以下幾個角色:

在享元模式中,具體享元對象之間可以共享內部狀態,而外部狀態是可變的,由客戶端代碼傳遞。享元工廠負責管理和創建享元對象,避免重復創建相同的享元對象。客戶端通過享元工廠獲取享元對象,并根據需要傳入外部狀態,從而定制享元對象的行為。這樣可以在節省內存空間的同時,實現定制化的復用。

  1. 享元(Flyweight):它是一個接口或抽象類,定義了具體享元對象的共享方法和獲取外部狀態方法。
  2. 具體享元(Concrete Flyweight):實現了享元接口,包含內部狀態和外部狀態兩部分。內部狀態是不變的,可以被多個享元對象共享;外部狀態是可變的,需要在使用時傳入。
  3. 享元工廠(Flyweight Factory):管理和創建享元對象,通過一個數據結構(如哈希表)存儲已經創建的享元對象,并根據需要進行復用或創建新的享元對象。
  4. 客戶端(Client):通過享元工廠來獲取享元對象,并根據需要傳入外部狀態。客戶端可以通過共享享元對象的內部狀態來節省內存空間和提高性能。

享元模式具體實現

以下實例通過創建歌曲享元工廠,實現歌曲的播放
享元接口

public interface Song {void play();
}

具體享元

/*** 國風歌曲*/
public class ChineseSong implements Song {private String songName;public ChineseSong(String songName) {this.songName = songName;}@Overridepublic void play() {System.out.println("A song called" + songName + " was played");}}

享元工廠

/*** 享元工廠類*/
public class FlyweightFactory {//定義一個集合,用于共享里面的對象private static Map<String, Song> songMap = new HashMap<>();public static ChineseSong getSong(String songName) {ChineseSong chineseSong = (ChineseSong) songMap.get(songName);if (chineseSong == null) {chineseSong = new ChineseSong(songName);songMap.put(songName, chineseSong);System.out.println("Add a new ChineseSong with : " + songName);}return chineseSong;}}

客戶端

/*** 享元模式* 利用享元模式實現播放歌曲*/
public class Flyweight {public static void main(String[] args) {Song 稻香 = FlyweightFactory.getSong("稻香");稻香.play();Song 花田錯 = FlyweightFactory.getSong("花田錯");花田錯.play();Song 稻香2 = FlyweightFactory.getSong("稻香");稻香2.play();}}

運行結果

Add a new ChineseSong with : 稻香
A song called稻香 was played
Add a new ChineseSong with : 花田錯
A song called花田錯 was played
A song called稻香 was played

在 FlyweightFactory中,使用了一個哈希表 Map 來存儲已經創建的 Song對象。在獲取 Song對象時,首先檢查 Map 中是否已存在該歌曲的對象,如果存在則直接返回,如果不存在則創建一個新的 Song對象,并將其加入到 Map 中。

享元模式的優缺點

享元模式的優點:

  1. 減少內存使用:享元模式通過共享對象來減少內存使用,特別是當有大量相似對象需要創建時。通過共享對象,可以節省大量的內存空間。
  2. 提高性能:由于享元模式共享對象,避免了頻繁地創建和銷毀對象,從而提高了系統的性能。
  3. 簡化復雜對象:享元模式可以將復雜對象拆分成多個簡單的共享對象,使得對象的創建和管理更加簡單。

享元模式的缺點:

  1. 共享對象的狀態不可變:由于享元對象被多個客戶端共享,因此其內部狀態必須是不可變的。如果某個客戶端修改了共享對象的狀態,可能會影響其他客戶端的操作。
  2. 對象共享可能增加復雜性:在實現享元模式時,需要對對象進行合理的劃分和管理,這可能增加系統的復雜性。
  3. 不適用于所有情況:享元模式主要適用于有大量相似對象需要共享的場景。對于不需要共享對象或者對象之間差異較大的情況,使用享元模式可能并不適合。
    享元模式在需要創建大量相似對象且需要節省內存的場景下具有很好的優勢,但也需要注意其適用性和狀態管理的復雜性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/34682.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/34682.shtml
英文地址,請注明出處:http://en.pswp.cn/news/34682.shtml

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

相關文章

Postman下載教程

目錄 下載 安裝 注意事項 看到很多小伙伴在問 Postman 下載的相關問題&#xff0c;花時間整理了下&#xff0c;下面教新入門的小伙伴如何去下載 Postman。 開始前我們可以先了解下&#xff1a;Postman 簡介 下載 第一步&#xff1a;進入 Postman 官網 首先&#xff0c;我…

maven打包上傳到私有倉庫的步驟

maven打包上傳到私有倉庫的步驟 一、pom.xml引入二、Maven的settings.xml三、pom.xml中添加源碼插件四、執行發布命令 先準備私庫地址&#xff1a; http://localhost:8081/nexus3/repository/maven-releases http://localhost:8081/nexus3/repository/maven-snapshots 假如現需…

如何在Vue表單處理中實現表單字段的文件下載

Vue.js 是一種流行的JavaScript框架&#xff0c;用于構建用戶界面。在Vue應用中&#xff0c;我們經常需要處理表單操作&#xff0c;其中一個常見需求是實現文件下載。以下介紹如何在Vue表單處理中實現表單字段的文件下載&#xff0c;大家共同交流。 一、使用HTML的a標簽實現文…

Java單例模式詳解(五種實現方式)

1、什么是單例模式&#xff1f; Java單例模式是一種設計模式&#xff0c;用于確保一個類只有一個實例&#xff0c;并提供全局訪問點以獲取該實例。它通常用于需要共享資源或控制某些共享狀態的情況下。 例如&#xff1a; 一個日志記錄器&#xff08;Logger&#xff09;。在一個…

二級考python和c語言哪個好,計算機二級python和c

大家好&#xff0c;小編來為大家解答以下問題&#xff0c;二級python和二級c語言哪個更吃香一些&#xff0c;二級python和二級c語言哪個更吃香一點&#xff0c;今天讓我們一起來看看吧&#xff01; 計算機二級貌似只是在校園里的自嗨&#xff0c;出來工作后并沒有覺得這個證書有…

JavaScript+Asp.Net MVC5同時下載多個文件

前端同時啟動多個下載任務&#xff08;但是沒有做壓縮包下載&#xff09; 前端JavaScript腳本&#xff1a; var idList [1,2,3];//要下載的列表 $.each(idList, function (index, item) {downloadURL("/File/GetPdf?id" item); });var count 0; var downloadUR…

LeetCode 21.合并兩個有序鏈表

文章目錄 &#x1f4a1;題目分析&#x1f4a1;解題思路&#x1f6a9;思路1: 歸并排序思想&#xff08;不使用帶哨兵衛的頭節點&#xff09;&#x1f514;接口源碼&#xff1a; &#x1f4a1;解題思路&#x1f6a9;思路2: 歸并排序思想&#xff08;使用帶哨兵衛的頭節點&#xf…

Ubuntu安裝JDK與IntelliJ IDEA

目錄 前言 Ubuntu 安裝 JDK 1、更新軟件包列表 2、安裝OpenJDK 3、驗證安裝 Ubuntu安裝IntelliJ IDEA 1、下載 IntelliJ IDEA 2、解壓縮 IntelliJ IDEA 安裝包 3、移動 IntelliJ IDEA 到安裝目錄 4、啟動 IntelliJ IDEA 前言 APT&#xff08;Advanced Package Tool&…

web-xss-dvwa

目錄 xss&#xff08;reflected&#xff09; low medium high xss(store) low medium high xss(dom) low medium high xss&#xff08;reflected&#xff09; low 沒有什么過濾&#xff0c;直接用最普通的標簽就可以了 http://127.0.0.1/DVWA-master/vulnerabili…

C++ STL vector 模擬實現

?<1>主頁&#xff1a;我的代碼愛吃辣 &#x1f4c3;<2>知識講解&#xff1a;C之STL &#x1f525;<3>創作者&#xff1a;我的代碼愛吃辣 ??<4>開發環境&#xff1a;Visual Studio 2022 &#x1f4ac;<5>前言&#xff1a;上次我們已經數字會用…

【uniapp使用web-view點擊返回報錯后返回不了】

問題及解決 問題解決 問題 使用web-view跳轉到別人的網站之后點擊返回報錯&#xff0c;返回不了 解決 使用以下方法 <template><view></view> </template> <script> var wv;//計劃創建的webview export default {onLoad() {// #ifdef APP-PL…

(杭電多校)2023“釘耙編程”中國大學生算法設計超級聯賽(7)

1002 Random Nim Game 只有3種情況,要么必贏,要么必輸,要么從宏觀角度考慮,隨機的話,贏的概率就是1/2(就像拋硬幣一樣,隨著拋的次數越來越多,正反面的概率將越來越接近1) 當只要有一堆石頭數量不是1,那么就是必贏或必輸,贏的概率就是1/2 當每堆石頭數量都為1時,當堆數為奇數…

unity新輸入系統的簡單使用(New InputSystem)

1、在包管理器 unity注冊表中下載安裝InputSystem 2、給玩家添加組件PlayerInput&#xff0c;點擊CreatAction,創建一個InputAct InputAct,這是玩家的輸入文件&#xff0c;在里面可以設置玩家輸入 3、使用 例如玩家控制角色移動 在InputAct中&#xff0c;默認已經設置好了移…

學習pytorch 2 導入查看dataset

學習pytorch 2 2. dataset實戰代碼數據集 2. dataset實戰 B站小土堆視頻 代碼 from torch.utils.data import Dataset from PIL import Image #import cv2 import osclass MyData(Dataset):def __init__(self, root_dir, label_dir):self.root_dir root_dirself.label_dir …

【Unity實戰100例】人物狀態欄UI數據刷新—MVC觀察者模式

目錄 一.創建Model層數據模型 二.創建View層關聯UI組件 三.創建Controller層使得V和M數據關聯 源碼:htt

[python]RuntimeError: Can‘t decrement id ref count (unable to close file...

使用spectralspatial模型進行EEG分類時&#xff0c;出現以下錯誤 RuntimeError: Cant decrement id ref count (unable to close file, errno 5, error message Input/output error) Segmentation fault (core dumped) 猜測是因為存儲的model太大了導致的&#xff0c;找到了…

hive 中最常用日期處理函數

hive 常用日期處理函數 在工作中&#xff0c;日期函數是提取數據計算數據必須要用到的環節。哪怕是提取某個時間段下的明細數據也得用到日期函數。今天和大家分享一下常用的日期函數。為什么說常用呢&#xff1f;其實這些函數在數據運營同學手上是幾乎每天都在使用的。 技術交…

FreeRTOS(計數信號量)

資料來源于硬件家園&#xff1a;資料匯總 - FreeRTOS實時操作系統課程(多任務管理) 目錄 一、計數信號量的定義與應用 1、計數信號量的定義 2、計數信號量的應用 二、計數信號量的運作機制 1、任務間計數信號量的實現 三、計數信號量常用的API函數 1、計數信號量典型流程…

雙指針算法

文章目錄 雙指針算法leetcode題目 雙指針算法 雙指針算法可以實現對于時間復雜度降一維度&#xff0c;使得O(n2)的算法時間復雜度變為O(n) 指針類型 對撞指針快慢指針 對撞指針 一般是用于順序結構中的&#xff0c;也可以稱為左右指針&#xff0c;從兩端向中間移動&#xff0c…

【工作中問題解決實踐 十一】Kafka消費者消費堆積且頻繁rebalance

最近有點不走運&#xff0c;老是遇到基礎服務的問題&#xff0c;還是記著點兒解決方法&#xff0c;以后再遇到快速解決吧&#xff0c;今天遇到這個問題倒不算緊急&#xff0c;但也能通過這個問題熟悉一下Kafka的配置。 問題背景 正在開會的時候突然收到一連串的報警&#xff…