举重设计模式示例
本文是我們名為“ Java設計模式 ”的學院課程的一部分。
在本課程中,您將深入研究大量的設計模式,并了解如何在Java中實現(xiàn)和利用它們。 您將了解模式如此重要的原因,并了解何時以及如何應用模式中的每一個。 在這里查看 !
目錄
1.節(jié)拍模式 2.什么是輕量級模式 3.解決問題 4.何時使用節(jié)拍模式 5. JDK中的Flyweight 6.下載源代碼1.節(jié)拍模式
面向對象的編程使編程變得簡單而有趣。 通過將真實世界的實體建模到編程世界中,它使程序員的工作更加輕松。 程序員創(chuàng)建一個類并通過創(chuàng)建一個對象來實例化它。 該對象建模真實世界的實體,應用程序內(nèi)部的對象相互協(xié)調,以完成所需的工作。
但是有時太多的對象會使速度變慢。 太多的對象可能會占用大量內(nèi)存,并且可能使應用程序變慢,甚至導致內(nèi)存不足問題。 作為一名優(yōu)秀的程序員,應該跟蹤實例化的對象并控制應用程序中的對象創(chuàng)建。 當我們有很多相似的對象并且池中的兩個對象之間沒有太大差異時,尤其如此。
有時,應用程序中的對象可能具有極大的相似性,并且具有相似的種類(此處相似的種類意味著它們的大多數(shù)屬性具有相似的值,而其中只有少數(shù)具有不同的值)。 如果它們也是很重的對象,則應由應用程序開發(fā)人員控制。 否則,它們可能會消耗大量內(nèi)存,并最終使整個應用程序變慢。
Flyweight模式旨在控制此類對象的創(chuàng)建,并為您提供基本的緩存機制。 它允許您為每種類型創(chuàng)建一個對象(此處的類型因該對象的屬性而異),并且如果您請求具有相同屬性(已創(chuàng)建)的對象,它將返回您相同的對象,而不是創(chuàng)建新的對象一。
在深入研究Flyweight模式的細節(jié)之前,讓我們考慮以下情形:一個允許用戶在線創(chuàng)建和執(zhí)行程序的站點。 我們現(xiàn)在將討論該場景,稍后將嘗試使用Flyweight模式解決該問題。
X編程站點允許用戶使用自己喜歡的編程語言來創(chuàng)建和執(zhí)行程序。 它為您提供了大量的編程語言選項。 您選擇一個,用它編寫程序并執(zhí)行以查看結果。
但是現(xiàn)在該網(wǎng)站已開始失去其用戶,原因是該網(wǎng)站運行緩慢。 用戶不再對此感興趣。 該網(wǎng)站非常受歡迎,有時可能有成千上萬的程序員在使用它。 因此,該網(wǎng)站正在爬網(wǎng)。 但是,大量使用并不是網(wǎng)站速度緩慢的真正問題。 讓我們看一下該站點的核心程序,該程序允許用戶運行和執(zhí)行其程序,真正的問題將在此處顯示。
package com.javacodegeeks.patterns.flyweightpattern;public class Code {private String code;public String getCode() {return code;}public void setCode(String code) {this.code = code;}}上面的類用于設置程序員完成的代碼,以使其執(zhí)行。 Code對象是一個輕量級的簡單對象,具有屬性code以及其setter和getter。
package com.javacodegeeks.patterns.flyweightpattern;public interface Platform {public void execute(Code code); }Platform接口由語言特定的平臺實現(xiàn),以便執(zhí)行代碼。 它有一個方法executes ,它以Code對象為參數(shù)。
package com.javacodegeeks.patterns.flyweightpattern;public class JavaPlatform implements Platform {public JavaPlatform(){System.out.println("JavaPlatform object created");}@Overridepublic void execute(Code code) {System.out.println("Compiling and executing Java code.");}}上面的類實現(xiàn)了Platform接口,并提供了execute方法的實現(xiàn),以執(zhí)行Java中的代碼。
要執(zhí)行該代碼,將創(chuàng)建一個包含該代碼的Code對象和一個用于執(zhí)行該代碼的Platform對象。 代碼如下:
Platform platform = new JavaPlatform(); platform.execute(code);現(xiàn)在假設,大約有2k個用戶在線并執(zhí)行他們的代碼,這導致2k個Code對象和2k Platform對象。 Code對象是一個輕量級的對象,每個用戶代碼也應該有一個Code對象。 但是, Platform是一個沉重的對象,用于設置執(zhí)行環(huán)境。 創(chuàng)建過多的Platform對象非常耗時,并且是繁重的工作。 我們需要控制可以使用Flyweight Pattern完成的Platform對象的創(chuàng)建,但在此之前,讓我們看一下Flyweight Pattern的細節(jié)。
2.什么是輕量級模式
Flyweight模式的目的是使用共享對象來有效地支持大量細粒度的對象。 flyweight是一個共享對象,可以同時在多個上下文中使用。 在每個上下文中,flyweight都充當一個獨立的對象–與未共享的對象實例是無法區(qū)分的。 舉重運動員不能對其工作環(huán)境進行假設。 這里的關鍵概念是固有狀態(tài)和外部狀態(tài)之間的區(qū)別。 內(nèi)在狀態(tài)存儲在舉重裝置中; 它包含的信息與舉重環(huán)境無關,因此可共享。 外在狀態(tài)取決于飛重的上下文并隨其變化,因此無法共享。 客戶對象負責在需要時將外部狀態(tài)傳遞給flyweight。
考慮一個涉及創(chuàng)建大量對象的應用程序場景,這些對象僅在幾個參數(shù)方面是唯一的。 換句話說,這些對象包含一些固有的,不變的數(shù)據(jù),這些數(shù)據(jù)在所有對象之間是通用的。 此固有數(shù)據(jù)需要作為正在創(chuàng)建的每個對象的一部分進行創(chuàng)建和維護。 就內(nèi)存使用和性能而言,大量此類對象的整體創(chuàng)建和維護可能非常昂貴。 Flyweight模式可用于此類情況,以設計創(chuàng)建對象的更有效方法。
這是Flyweight設計模式的類圖:
圖1
飛行重量
- 聲明一個接口,權重可以通過該接口接收外部狀態(tài)并對其進行操作。
混凝土飛艇
- 實現(xiàn)Flyweight接口,并為固有狀態(tài)添加存儲(如果有)。 ConcreteFlyweight對象必須是可共享的。 它存儲的任何狀態(tài)都必須是固有的。 也就是說,它必須獨立于ConcreteFlyweight對象的上下文。
FlyweightFactory
- 創(chuàng)建和管理重量級對象。
- 確保飛行重量正確共享。 當客戶端請求一個flyweight時,FlyweightFactory對象提供一個現(xiàn)有實例或創(chuàng)建一個實例(如果不存在)。
客戶
- 維護對輕量化的參考。
- 計算或存儲飛行重量的外部狀態(tài)。
3.解決問題
為了解決上述問題,我們將提供一個平臺工廠類,該類將控制Platform對象的創(chuàng)建。
package com.javacodegeeks.patterns.flyweightpattern;import java.util.HashMap; import java.util.Map;public final class PlatformFactory {private static Map<String, Platform> map = new HashMap<>();private PlatformFactory(){throw new AssertionError("Cannot instantiate the class");}public static synchronized Platform getPlatformInstance(String platformType){Platform platform = map.get(platformType);if(platform==null){switch(platformType){case "C" : platform = new CPlatform(); break;case "CPP" : platform = new CPPPlatform(); break;case "JAVA" : platform = new JavaPlatform(); break;case "RUBY" : platform = new RubyPlatform(); break; }map.put(platformType, platform);}return platform;}}上面的類包含一個靜態(tài)映射,其中包含一個String對象作為鍵,一個Platform類型的對象作為其值。 我們不想創(chuàng)建此類的實例,因此只需將其構造函數(shù)保留為私有狀態(tài),并拋出AssertionError只是為了避免即使在類內(nèi)也意外創(chuàng)建了該對象。
此類的主要方法也是唯一方法是getPlatformInstance方法。 這是一個靜態(tài)方法,其參數(shù)為platformType 。 該platformType用作地圖中的鍵,它首先檢查地圖是否已經(jīng)存在具有該鍵的平臺對象。 如果未找到對象,則創(chuàng)建適當?shù)钠脚_對象,將其放入地圖中,然后該方法返回該對象。 下次,當請求相同的平臺類型對象時,將返回相同的現(xiàn)有對象,而不是新的對象。
另外,請注意, getPlatformInstance方法是synchronized ,以便在檢查和創(chuàng)建對象實例時提供線程安全。 在上面的示例中,沒有共享對象的任何內(nèi)在屬性,而只有外部屬性,即由客戶端代碼提供的代碼對象。
現(xiàn)在,讓我們測試代碼。
package com.javacodegeeks.patterns.flyweightpattern;public class TestFlyweight {public static void main(String[] args) {Code code = new Code();code.setCode("C Code...");Platform platform = PlatformFactory.getPlatformInstance("C");platform.execute(code);System.out.println("-------------------------------------");code = new Code();code.setCode("C Code2...");platform = PlatformFactory.getPlatformInstance("C");platform.execute(code);System.out.println("-------------------------------------");code = new Code();code.setCode("JAVA Code...");platform = PlatformFactory.getPlatformInstance("JAVA");platform.execute(code);System.out.println("-------------------------------------");code = new Code();code.setCode("JAVA Code2...");platform = PlatformFactory.getPlatformInstance("JAVA");platform.execute(code);System.out.println("-------------------------------------");code = new Code();code.setCode("RUBY Code...");platform = PlatformFactory.getPlatformInstance("RUBY");platform.execute(code);System.out.println("-------------------------------------");code = new Code();code.setCode("RUBY Code2...");platform = PlatformFactory.getPlatformInstance("RUBY");platform.execute(code);}}上面的代碼將導致以下輸出:
CPlatform object created Compiling and executing C code. ------------------------------------- Compiling and executing C code. ------------------------------------- JavaPlatform object created Compiling and executing Java code. ------------------------------------- Compiling and executing Java code. ------------------------------------- RubyPlatform object created Compiling and executing Ruby code. ------------------------------------- Compiling and executing Ruby code.在上面的類中,我們首先創(chuàng)建了一個Code對象,并在其中設置了C代碼。 然后,我們要求PlatformFactory提供C平臺來執(zhí)行代碼。 后來,我們對返回的對象調用了execute方法,從而繞過了它的Code對象。
我們執(zhí)行相同的過程,即創(chuàng)建和設置Code對象,然后請求特定于代碼的平臺對象。 輸出清楚地表明,平臺對象只是在第一次請求時創(chuàng)建的; 在下一次嘗試中,將返回相同的對象。
其他特定于平臺的類類似于已經(jīng)顯示的JavaPlatform類。
package com.javacodegeeks.patterns.flyweightpattern;public class CPlatform implements Platform {public CPlatform(){System.out.println("CPlatform object created");}@Overridepublic void execute(Code code) {System.out.println("Compiling and executing C code.");}}package com.javacodegeeks.patterns.flyweightpattern;public class CPPPlatform implements Platform{public CPPPlatform(){System.out.println("CPPPlatform object created");}@Overridepublic void execute(Code code) {System.out.println("Compiling and executing CPP code.");}}package com.javacodegeeks.patterns.flyweightpattern;public class RubyPlatform implements Platform{public RubyPlatform(){System.out.println("RubyPlatform object created");}@Overridepublic void execute(Code code) {System.out.println("Compiling and executing Ruby code.");}}如果我們重新考慮2k用戶同時使用該站點,則將精確地創(chuàng)建2k輕量級Code對象,并且僅實例化4個重量級平臺對象。 請注意,考慮到每種語言至少有一個用戶,我們說的是4個平臺對象。 例如,如果假設沒有用戶使用Ruby進行編碼,則在該場景中僅創(chuàng)建3個平臺對象。
4.何時使用節(jié)拍模式
Flyweight模式的有效性在很大程度上取決于其使用方式和位置。 當滿足以下所有條件時,應用Flyweight模式:
- 應用程序使用大量對象。
- 由于對象數(shù)量巨大,因此存儲成本很高。
- 大多數(shù)對象狀態(tài)可以是外部的。
- 一旦刪除了外部狀態(tài),許多對象組可能會被相對較少的共享對象替換。
- 該應用程序不依賴于對象標識。 由于可以共享輕量級對象,因此對于概念上不同的對象,身份測試將返回true。
5. JDK中的Flyweight
以下是JDK中Flyweight模式的用法。
- java.lang.Integer#valueOf(int) (也適用于Boolean,Byte,Character,Short和Long)
6.下載源代碼
這是關于節(jié)拍模式的一課。 您可以在此處下載源代碼: Flyweight Pattern Project
翻譯自: https://www.javacodegeeks.com/2015/09/flyweight-design-pattern.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結
- 上一篇: 小机灵鬼是什么意思 小机灵鬼是啥意思
- 下一篇: 女朋友用英语怎么说 女朋友英文简介