摘要:類圖相關的設計模式享元模式和代理模式當代理模式消耗性能比較大的時候,就可以用享元模式享元模式和單例模式容器單例,享元模式就是復用對象的思想。源碼中的享元模式源碼地址享元模式參考慕課網(wǎng)設計模式精講設計模式讀書筆記享元模式
0x01.定義與類型
定義:提供了減少對象數(shù)量從而改善應用所需的對象結構的方法,系統(tǒng)使用少量對象,而且這些都比較相似,狀態(tài)變化小,可以實現(xiàn)對象的多次復用。
運用共享技術有效地支持大量細粒度的對象
類型:結構型
享元模式的兩個狀態(tài):
內(nèi)部狀態(tài):在享元對象內(nèi)部不隨外界環(huán)境改變而改變的共享部分。
外部狀態(tài):隨著環(huán)境的改變而改變,不能夠共享的狀態(tài)就是外部狀態(tài)。
由于享元模式區(qū)分了內(nèi)部狀態(tài)和外部狀態(tài),所以我們可以通過設置不同的外部狀態(tài)使得相同的對象可以具備一些不同的特性,而內(nèi)部狀態(tài)設置為相同部分。在我們的程序設計過程中,我們可能會需要大量的細粒度對象來表示對象,如果這些對象除了幾個參數(shù)不同外其他部分都相同,這個時候我們就可以利用享元模式來大大減少應用程序當中的對象。如何利用享元模式呢?這里我們只需要將他們少部分的不同的部分當做參數(shù)移動到類實例的外部去,然后再方法調用的時候將他們傳遞過來就可以了。這里也就說明了一點:內(nèi)部狀態(tài)存儲于享元對象內(nèi)部,而外部狀態(tài)則應該由客戶端來考慮。
UML類圖
Java實現(xiàn)
/** * 享元對象接口 */ public interface Flyweight { void operation(String extrinsicState); } /** * 享元對象工廠類,享元類 */ public final class FlyweightFactory { /** * 享元類容器 */ private static Mapflyweights = new HashMap<>(); public static Flyweight getFlyweight (String key) { if (flyweights.containsKey(key)) { return flyweights.get(key); } else { Flyweight flyweight = new ConcreteFlyweight(key); flyweights.put(key, flyweight); return flyweight; } } public static int size () { return flyweights.size(); } } /** * 可以被共享的對象 */ public class ConcreteFlyweight implements Flyweight{ private String intrinsicState; public ConcreteFlyweight(String intrinsicState) { this.intrinsicState = intrinsicState; } @Override public void operation(String extrinsicState) { System.out.println(this.intrinsicState); System.out.println(extrinsicState); } } /** * 不被共享的對象 */ public class UnsharedConcreteFlyweight implements Flyweight { private String allState; public UnsharedConcreteFlyweight(String allState) { this.allState = allState; } @Override public void operation(String extrinsicState) { System.out.println(this.allState); System.out.println(extrinsicState); } }
測試與應用類
/** * 應用與測試 */ public class Test { public static void main(String[] args) { Stream.of("1", "1", "2", "2", "3").forEach(key -> { Flyweight flyweight = FlyweightFactory.getFlyweight(key); flyweight.operation("測試" + key); }); System.out.println("size: " + FlyweightFactory.size()); } }
輸出結果
1---:測試1 1---:測試1 2---:測試2 2---:測試2 3---:測試3 size: 3
享元模式角色介紹
Flyweight: 抽象享元類。所有具體享元類的超類或者接口,通過這個接口,F(xiàn)lyweight可以接受并作用于外部專題。
ConcreteFlyweight: 具體享元類。指定內(nèi)部狀態(tài),為內(nèi)部狀態(tài)增加存儲空間。
UnsharedConcreteFlyweight: 非共享具體享元類。指出那些不需要共享的Flyweight子類。
FlyweightFactory: 享元工廠類。用來創(chuàng)建并管理Flyweight對象,它主要用來確保合理地共享Flyweight,當用戶請求一個Flyweight時,F(xiàn)lyweightFactory就會提供一個已經(jīng)創(chuàng)建的Flyweight對象或者新建一個(如果不存在)。
享元模式的核心在于享元工廠類,享元工廠類的作用在于提供一個用于存儲享元對象的享元池,用戶需要對象時,首先從享元池中獲取,如果享元池中不存在,則創(chuàng)建一個新的享元對象返回給用戶,并在享元池中保存該新增對象。
0x02.適用場景如果一個系統(tǒng)中存在大量的相同或者相似的對象,由于這類對象的大量使用,會造成系統(tǒng)內(nèi)存的耗費,可以使用享元模式緩沖池來減少系統(tǒng)中對象的數(shù)量。
對象的大部分狀態(tài)都可以外部化,可以將這些外部狀態(tài)傳入對象中。
常常應用于系統(tǒng)底層的開發(fā),以便解決系統(tǒng)的性能問題。
0x03.優(yōu)點減少對象的創(chuàng)建,降低內(nèi)存中對象的數(shù)量,降低系統(tǒng)的內(nèi)存,提高效率。
減少內(nèi)存之外的其他資源占用。
0x04.缺點由于享元模式需要區(qū)分外部狀態(tài)和內(nèi)部狀態(tài),使得應用程序在某種程度上來說更加復雜化了。
為了使對象可以共享,享元模式需要將享元對象的狀態(tài)外部化,而讀取外部狀態(tài)使得運行時間變長。
需要關注內(nèi)/外部狀態(tài),關注線程安全問題。
0x05.模式樣例假設一個公司中的每個部門的部門經(jīng)理都要進行匯報不止一次
Java實現(xiàn)
/** * 員工接口 */ public interface Employee { void report(); } /** * 員工工廠 */ public class EmployeeFactory { private static final MapEMPLOYEE_MAP = new HashMap<>(); public static Employee getManager(String department) { Manager manager = (Manager) EMPLOYEE_MAP.get(department); if (manager == null) { manager = new Manager(department); System.out.println("創(chuàng)建部門經(jīng)理:" + department); String reportContent = department + "部門匯報:此次報告內(nèi)容是。。。"; manager.setReportContent(reportContent); System.out.println("創(chuàng)建報告: " + reportContent); EMPLOYEE_MAP.put(department, manager); } return manager; } } /** * 部門經(jīng)理 */ public class Manager implements Employee { /** * 內(nèi)部狀態(tài) */ private String title = "部門經(jīng)理"; /** * 外部狀態(tài),需要在應用層引入,就是外部狀態(tài) */ private String department; private String reportContent; public Manager(String department) { this.department = department; } public void setReportContent(String reportContent) { this.reportContent = reportContent; } @Override public void report() { System.out.println(reportContent); } }
測試與應用
/** * 測試與應用 */ public class Test { private static final String[] departments = {"RD", "QA", "PM", "BD"}; /** * 要注意線程安全的問題 */ public static void main(String[] args) { for (int i = 0; i < 10; i ++) { String department = departments[(int) (Math.random() * departments.length)]; Manager manager = (Manager) EmployeeFactory.getManager(department); manager.report(); } System.out.println(EmployeeFactory.size()); } }
輸出結果
創(chuàng)建部門經(jīng)理:BD 創(chuàng)建報告: BD部門匯報:此次報告內(nèi)容是。。。 BD部門匯報:此次報告內(nèi)容是。。。 創(chuàng)建部門經(jīng)理:PM 創(chuàng)建報告: PM部門匯報:此次報告內(nèi)容是。。。 PM部門匯報:此次報告內(nèi)容是。。。 創(chuàng)建部門經(jīng)理:QA 創(chuàng)建報告: QA部門匯報:此次報告內(nèi)容是。。。 QA部門匯報:此次報告內(nèi)容是。。。 QA部門匯報:此次報告內(nèi)容是。。。 QA部門匯報:此次報告內(nèi)容是。。。 BD部門匯報:此次報告內(nèi)容是。。。 PM部門匯報:此次報告內(nèi)容是。。。 創(chuàng)建部門經(jīng)理:RD 創(chuàng)建報告: RD部門匯報:此次報告內(nèi)容是。。。 RD部門匯報:此次報告內(nèi)容是。。。 PM部門匯報:此次報告內(nèi)容是。。。 PM部門匯報:此次報告內(nèi)容是。。。 4
UML類圖
0x06.相關的設計模式享元模式和代理模式:當代理模式消耗性能比較大的時候,就可以用享元模式
享元模式和單例模式:容器單例,享元模式就是復用對象的思想。
0x07.源碼中的享元模式JDK: Integer.valueOf(), --IntegerCache
Tomcat: GenericObjectPoolConfig, GenericKeyedPoolConfig
0x08.源碼地址享元模式: https://github.com/sigmako/design-pattern/tree/master/fiyweight
0x09.參考慕課網(wǎng)設計模式精講: https://coding.imooc.com/class/270.html
設計模式讀書筆記----享元模式: https://www.cnblogs.com/chenssy/p/3330555.html
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/75811.html
摘要:作者按每天一個設計模式旨在初步領會設計模式的精髓,目前采用和兩種語言實現(xiàn)。享元模式提醒我們將一個對象的屬性劃分為內(nèi)部和外部狀態(tài)。 作者按:《每天一個設計模式》旨在初步領會設計模式的精髓,目前采用javascript和python兩種語言實現(xiàn)。誠然,每種設計模式都有多種實現(xiàn)方式,但此小冊只記錄最直截了當?shù)膶崿F(xiàn)方式 :) 個人技術博客-godbmw.com 歡迎來玩! 每周至少 1 篇原創(chuàng)...
摘要:作者按每天一個設計模式旨在初步領會設計模式的精髓,目前采用和兩種語言實現(xiàn)。享元模式提醒我們將一個對象的屬性劃分為內(nèi)部和外部狀態(tài)。 作者按:《每天一個設計模式》旨在初步領會設計模式的精髓,目前采用javascript和python兩種語言實現(xiàn)。誠然,每種設計模式都有多種實現(xiàn)方式,但此小冊只記錄最直截了當?shù)膶崿F(xiàn)方式 :) 個人技術博客-godbmw.com 歡迎來玩! 每周至少 1 篇原創(chuàng)...
摘要:享元模式享元模式是一種優(yōu)化程序性能的模式本質為減少對象創(chuàng)建的個數(shù)。 享元模式 享元模式是一種優(yōu)化程序性能的模式, 本質為減少對象創(chuàng)建的個數(shù)。 以下情況可以使用享元模式:有大量相似的對象, 占用了大量內(nèi)存對象中大部分狀態(tài)可以抽離為外部狀態(tài) demo某商家有 50 種男款內(nèi)衣和 50 種款女款內(nèi)衣, 要展示它們 方案一: 造 50 個塑料男模和 50 個塑料女模, 讓他們穿上展示, 代碼如...
摘要:享元模式通過分析應用程序的對象,將其解析為內(nèi)在數(shù)據(jù)和外在數(shù)據(jù),減少對象數(shù)量,從而提高程序的性能。通過這種方式進行事件綁定,可以減少事件處理程序的數(shù)量,這種方式叫做事件委托,也是運用了享元模式的原理。事件處理程序是公用的內(nèi)在部分,每個菜單項各 github 全文地址 : YOU-SHOULD-KNOW-JS JavaScript設計模式之外觀模式 概念 外觀模式:為一組復雜子系統(tǒng)接口提...
閱讀 1280·2021-10-14 09:50
閱讀 1580·2019-08-30 15:54
閱讀 1040·2019-08-30 11:22
閱讀 2934·2019-08-30 10:50
閱讀 1817·2019-08-29 18:39
閱讀 3067·2019-08-29 13:07
閱讀 2090·2019-08-28 17:54
閱讀 761·2019-08-26 17:44