摘要:享元模式屬于結構型模式的一種,又稱輕量級模式,通過共享技術有效地實現了大量細粒度對象的復用概述兩種結構狀態內部狀態享元對象內部不隨外界環境改變而改變的共享部分。
概述享元模式(Flyweight Pattern)屬于結構型模式的一種,又稱輕量級模式,通過共享技術有效地實現了大量細粒度對象的復用...
兩種結構狀態
內部狀態:享元對象內部不隨外界環境改變而改變的共享部分。
外部狀態:享元對象內部隨環境的改變而改變,不能夠共享的狀態就是外部狀態。
結構圖
存在的角色
Flyweight(抽象享元類):通常是一個接口或抽象類,向外界提供享元對象的內部數據(內部狀態)或外部數據(外部狀態)。
ConcreteFlyweight(具體享元類):實現了Flyweight(抽象享元類)也稱為享元對象,指定內部狀態,為內部狀態增加存儲空間。通常我們可以結合單例模式來設計具體享元類,為每一個具體享元類提供唯一的享元對象。
UnsharedConcreteFlyweight(非共享具體享元類):指不需要共享的Flyweight子類。
FlyweightFactory(享元工廠類):用于創建并管理享元對象,針對抽象享元類編程,將各種類型的具體享元對象存儲在一個享元池中,享元池一般設計為鍵值對的集合(也可以是其他類型的集合),同時可以結合工廠模式進行設計。
享元模式的核心在于享元工廠類,享元工廠類的作用在于提供一個用于存儲享元對象的享元池,用戶需要對象時,首先從享元池中獲取,如果享元池中不存在,則創建一個新的享元對象返回給用戶,并在享元池中保存該新增對象。
案例案例UML圖如下:
1.創建Flyweight接口/抽象類
interface Flyweight { void operation(String name); String getType(); }
2.創建ConcreteFlyweight(享元對象),實現了Flyweight接口
class ConcreteFlyweight implements Flyweight { private String type; public ConcreteFlyweight(String type) { this.type = type; } @Override public void operation(String name) { System.out.printf("[類型(內在狀態)] - [%s] - [名字(外在狀態)] - [%s] ", type, name); } @Override public String getType() { return type; } }
3.創建FlyweightFactory(享元工廠類),用來維護享元池
class FlyweightFactory { private static final MapFLYWEIGHT_MAP = new HashMap<>(); public static Flyweight getFlyweight(String type) { if (FLYWEIGHT_MAP.containsKey(type)) { return FLYWEIGHT_MAP.get(type); } else { ConcreteFlyweight flyweight = new ConcreteFlyweight(type); FLYWEIGHT_MAP.put(type, flyweight); return flyweight; } } public static int total() { return FLYWEIGHT_MAP.size(); } }
4.創建Client(測試類)
public class Client { public static void main(String[] args) { Flyweight fw0 = FlyweightFactory.getFlyweight("戰士"); Flyweight fw1 = FlyweightFactory.getFlyweight("戰士"); Flyweight fw2 = FlyweightFactory.getFlyweight("法師"); Flyweight fw3 = FlyweightFactory.getFlyweight("坦克"); fw1.operation("瑞文"); fw1.operation("鱷魚"); fw2.operation("光輝"); fw3.operation("泰坦"); fw3.operation("蓋倫"); System.out.printf("[結果(對象對比)] - [%s] ", fw0 == fw1); System.out.printf("[結果(內在狀態)] - [%s] ", fw1.getType()); System.out.printf("一共召喚 %s 種類型英雄 ", FlyweightFactory.total()); } }
5.運行結果,從結果中可以發現,只生成了3個不同的類
[類型(內在狀態)] - [戰士] - [名字(外在狀態)] - [瑞文] [類型(內在狀態)] - [戰士] - [名字(外在狀態)] - [鱷魚] [類型(內在狀態)] - [法師] - [名字(外在狀態)] - [光輝] [類型(內在狀態)] - [坦克] - [名字(外在狀態)] - [泰坦] [類型(內在狀態)] - [坦克] - [名字(外在狀態)] - [蓋倫] [結果(對象對比)] - [true] [結果(內在狀態)] - [戰士] 一共召喚 3 種類型英雄JDK中使用
在JAVA語言中,String類型就是使用了享元模式。String對象是final類型,對象一旦創建就不可改變。在JAVA中字符串常量都是存在常量池中的,JAVA會確保一個字符串常量在常量池中只有一個拷貝。
public class Client { public static void main(String[] args) { String a = "蓋倫"; String b = "蓋倫"; System.out.println(a==b);// 返回 true } }
上面的例子中結果為:true,這就說明a和b兩個引用都指向了常量池中的同一個字符串常量。這樣設計的目的就是:為了避免在創建多相同對象時,所產生的不必要的資源消耗。
總結如果程序里使用大量相同或者相似的對象,造成內存的大量耗費,且大多都是外部狀態,這時候就應該考慮使用享元模式了,比如圍棋、五子棋等小游戲
優點
能夠極大的減少系統中對象的個數。
外部狀態相對獨立,不會影響到內部狀態,能夠使享元對象在不同的環境被共享。
缺點
由于享元模式需要區分外部狀態和內部狀態,使得程序在某種程度上來說更加復雜化了。
為了使對象可以共享,享元模式需要將享元對象的狀態外部化,而讀取外部狀態使得運行時間變長。
- 說點什么全文代碼:https://gitee.com/battcn/design-pattern/tree/master/Chapter9/battcn-flyweight
個人QQ:1837307557
battcn開源群(適合新手):391619659
微信公眾號:battcn(歡迎調戲)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/68022.html
摘要:類的適配器結構目標角色這就是所期待得到的接口,由于是類適配器模式,因此目標不可以是類。這種類型的設計模式屬于結構型模式,它是作為現有的類的一個包裝。和適配器模式的關系適配器模式的用意是改變所考慮對象的接口,而代理模式不能改變。 點擊進入我的博客 3.1 適配器模式 適配器模式把一個類的接口變換成客戶端所期待的另一種接口,使得原本因接口不匹配而無法在一起工作的兩個類能夠在一起工作。 3...
摘要:本文只是尋找設計模式在中的應用。來補全這一塊工廠模式中的應用包線程池解釋和代碼線程池中有線程創建工廠。狀態模式中的應用解釋和代碼根據一個指針的狀態而改變自己的行為適配器模式中的應用解釋和代碼將一個類的接口轉換成客戶希望的另外一個接口。 前言 最近重學設計模式,而且還有很多源碼要看。所以就想一舉兩得。從源碼中尋找設計模式。順便還可以看看源碼。。。本文只是尋找設計模式在java中的應用。優...
摘要:抽象工廠模式是為了處理對象具有等級結構以及對象族的問題。單例設計模式單例模式確保某一個類只有一個實例,而且自行實例化并向整個系統提供這個實例,這個類成為單例類。 導語:設計模式是無數碼農前人在實際的生產項目中經過不斷的踩坑、爬坑、修坑的經歷總結出來的經驗教訓,經過抽象之后表達成的概念。能夠幫助后來的設計者避免重復同樣的錯誤或者彎路。我也抽空整理了一下設計模式,用自己的話總結了一下,自認...
閱讀 2831·2021-09-28 09:45
閱讀 1507·2021-09-26 10:13
閱讀 897·2021-09-04 16:45
閱讀 3661·2021-08-18 10:21
閱讀 1084·2019-08-29 15:07
閱讀 2633·2019-08-29 14:10
閱讀 3147·2019-08-29 13:02
閱讀 2459·2019-08-29 12:31