真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Java的享元模式是什么

本篇內(nèi)容主要講解“Java的享元模式是什么”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Java的享元模式是什么”吧!

站在用戶的角度思考問題,與客戶深入溝通,找到鹿城網(wǎng)站設(shè)計(jì)與鹿城網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、申請(qǐng)域名虛擬主機(jī)、企業(yè)郵箱。業(yè)務(wù)覆蓋鹿城地區(qū)。

前言

試想一下,如果我們要用程序來(lái)設(shè)計(jì)圍棋游戲,黑子181枚,白子180枚,那我們是不是每下一個(gè)子時(shí),都要去new一個(gè)棋子對(duì)象呢?Java是一門面向?qū)ο笳Z(yǔ)言,我們都知道如果在內(nèi)存中不停的new新對(duì)象時(shí),當(dāng)對(duì)象數(shù)量太多時(shí),又回收不及時(shí)時(shí),將導(dǎo)致運(yùn)行代價(jià)過高,帶來(lái)性能下降等問題。那我們?cè)趺慈ソ鉀Q這類問題呢?下面,將為大家講解本篇的重點(diǎn),Java設(shè)計(jì)模式之——享元模式。

什么是享元模式

為了方便理解,我們先來(lái)看一下享元模式的兩種狀態(tài):

  • 內(nèi)部狀態(tài)(Intrinsic State):是存儲(chǔ)在享元對(duì)象內(nèi)部并且不會(huì)隨環(huán)境改變而改變的狀態(tài),因此內(nèi)部狀態(tài)可以共享。

  • 外部狀態(tài)(Extrinsic State):是隨環(huán)境改變而改變的、不可以共享的狀態(tài)。享元對(duì)象的外部狀態(tài)必須由客戶端保存,并在享元對(duì)象被創(chuàng)建之后,在需要使用的時(shí)候再傳入到享元對(duì)象內(nèi)部。一個(gè)外部狀態(tài)與另一個(gè)外部狀態(tài)之間是相互獨(dú)立的。

享元模式將一個(gè)對(duì)象的狀態(tài)分為內(nèi)部狀態(tài)和外部狀態(tài),其中,二者是相互獨(dú)立的,共享相同的內(nèi)部狀態(tài),通過設(shè)置不同的外部狀態(tài)來(lái)改變對(duì)象的特征,讓一個(gè)對(duì)象擁有不同的特征,但內(nèi)部狀態(tài)始終是共享的,不可改變的。也就是,改變外部狀態(tài)不會(huì)引起內(nèi)部狀態(tài)改變。

可以把圍棋想象成享元模式,他們的大小、形狀、顏色是內(nèi)部狀態(tài),棋子的位置是外部狀態(tài),這樣在設(shè)計(jì)時(shí),只需要設(shè)置黑白棋子兩個(gè)對(duì)象,黑棋共享黑色的內(nèi)部狀態(tài),白棋共享白色的內(nèi)部狀態(tài),棋盤上每個(gè)棋子的位置就是他們的外部狀態(tài),圍棋盤361個(gè)交叉點(diǎn)位置,棋子每落一個(gè)位置(外部狀態(tài)),都不會(huì)改變棋子的顏色(內(nèi)部狀態(tài))。這樣是不是好理解一點(diǎn)。

享元模式一般會(huì)結(jié)合工廠模式使用,目的是為了創(chuàng)建一個(gè)享元工廠來(lái)負(fù)責(zé)維護(hù)享元池(Flyweight Pool),享元池里存放的是具有相同內(nèi)部狀態(tài)的享元對(duì)象。在實(shí)際的日常業(yè)務(wù)的千變?nèi)f化中,能夠共享的內(nèi)部狀態(tài)是很少的,所以享元對(duì)象一般都設(shè)計(jì)為較小的對(duì)象,包含的內(nèi)部狀態(tài)也很少,這種對(duì)象也成為細(xì)粒度對(duì)象。

現(xiàn)在我們來(lái)看一下享元模式的英文定義:

Flyweight Pattern: Use sharing to support large numbers of fine-grained objects efficiently.

翻譯過來(lái)就是:運(yùn)用共享技術(shù)有效地支持大量細(xì)粒度對(duì)象的復(fù)用。(Flyweight我不也不懂為什么國(guó)內(nèi)都翻譯成享元,沒找到資料,可能是根據(jù)這個(gè)模式的作用和特性翻譯來(lái)的,如果有知道的朋友煩請(qǐng)文末留言告知一聲,謝謝?。?/p>

再看一下國(guó)內(nèi)對(duì)享元模式的解釋:

享元模式(Flyweight Pattern):運(yùn)用共享技術(shù)有效地支持大量細(xì)粒度對(duì)象的復(fù)用。系統(tǒng)只使用少量的對(duì)象,而這些對(duì)象都很相似,狀態(tài)變化很小,可以實(shí)現(xiàn)對(duì)象的多次復(fù)用。由于享元模式要求能夠共享的對(duì)象必須是細(xì)粒度對(duì)象,因此它又稱為輕量級(jí)模式,它是一種對(duì)象結(jié)構(gòu)型模式。

簡(jiǎn)而言之:享元模式的目的就是通過共享不變的部分,達(dá)到減少對(duì)象數(shù)量并節(jié)約內(nèi)存的目的。

享元模式的四個(gè)角色

  • Flyweight(抽象享元類):接口或抽象類,聲明公共方法,這些方法可以向外界提供對(duì)象的內(nèi)部狀態(tài),設(shè)置外部狀態(tài)。

  • ConcreteFlyweight(具體享元類):實(shí)現(xiàn)了抽象享元類,其實(shí)例稱為享元對(duì)象。必須是可共享的,需要封裝享元對(duì)象的內(nèi)部狀態(tài);。

  • UnsharedConcreteFlyweight(非共享具體享元類):非共享的享元實(shí)現(xiàn)對(duì)象,并不是所有的享元對(duì)象都可以共享,非共享的享元對(duì)象通常是享元對(duì)象的組合對(duì)象。

  • FlyweightFactory(享元工廠類):享元工廠,主要用來(lái)創(chuàng)建并管理共享的享元對(duì)象,并對(duì)外提供訪問共享享元的接口。它針對(duì)抽象享元類編程,將各種類型的具體享元對(duì)象存儲(chǔ)在一個(gè)享元池中,享元池一般設(shè)計(jì)為一個(gè)存儲(chǔ)“鍵值對(duì)”的集合(也可以是其他類型的集合),可以結(jié)合工廠模式進(jìn)行設(shè)計(jì);當(dāng)用戶請(qǐng)求一個(gè)具體享元對(duì)象時(shí),享元工廠提供一個(gè)存儲(chǔ)在享元池中已創(chuàng)建的實(shí)例或者創(chuàng)建一個(gè)新的實(shí)例(如果不存在的話),返回新創(chuàng)建的實(shí)例并將其存儲(chǔ)在享元池中。

享元模式的UML圖

Java的享元模式是什么

代碼實(shí)例

我就不用我和李大爺下棋的例子了,以免在他老大(幼?。┑男撵`上留下創(chuàng)傷。關(guān)于棋子的案例,網(wǎng)上也有很多版本,大家感興趣的可以自己去看。下面我們用王者榮耀游戲來(lái)舉例。我們知道,在一局對(duì)戰(zhàn)賽里,每隔幾分鐘就會(huì)出現(xiàn)一波小兵和超級(jí)兵,小兵都長(zhǎng)的一模一樣,超級(jí)兵也是,如果王者團(tuán)隊(duì)在設(shè)計(jì)小兵出場(chǎng)的時(shí)候,每出來(lái)一個(gè)小兵,就new一個(gè)小兵對(duì)象,那么在這個(gè)幾百萬(wàn)甚至更多人同時(shí)在線角逐的游戲里,服務(wù)器壓力根本就頂不住,還能不能好好的、流暢的、愉快的上分了,小學(xué)生放學(xué)后早就乖乖在家做作業(yè)了。

那么怎樣設(shè)計(jì)呢?我們可以將小兵的體征、裝配、兵種作為內(nèi)部狀態(tài),然后它們?cè)诘貓D上出擊的方向作為外部狀態(tài),這樣無(wú)論小兵從哪個(gè)方向出擊(外部狀態(tài)怎樣改變),都不會(huì)改變小兵的體征和兵種(內(nèi)部狀態(tài)),這樣我們?cè)陂_發(fā)時(shí),每個(gè)兵種只要有一個(gè)享元對(duì)象就可以了。來(lái)看代碼:

1、編寫抽象享元類

package com.weiya.mazhichu.designpatterns.flyweight;

/**
 * 
 * 功能:抽象享元類
 * 

 *  * @author Moore  * @ClassName Soldier flyweight.  * @Version V1.0.  * @date 2019.09.03 21:06:52  */ public interface SoldierFlyweight {     /**      *       * 功能:敵軍出擊方法      * 

     *      * @param direction :      * @author Moore      * @date 2019.09.03 21:06:52      */     public void attack(String direction); }

2、編寫具體享元類

package com.weiya.mazhichu.designpatterns.flyweight;

/**
 * 
 * 功能:具體享元類
 * 

 *  * @author Moore  * @ClassName Concrete solider flyweight.  * @Version V1.0.  * @date 2019.09.04 09:45:41  */ public class ConcreteSoliderFlyweight implements SoldierFlyweight {     // 內(nèi)部狀態(tài)     private String soliderType;     public ConcreteSoliderFlyweight(String soliderType) {         this.soliderType = soliderType;     }     @Override     public void attack(String direction) {         if("normal".equals(soliderType)){             System.out.println("普通兵加入戰(zhàn)場(chǎng)");         }         if("super".equals(soliderType)){             System.out.println("超級(jí)兵加入戰(zhàn)場(chǎng)");         }         System.out.println("出擊方向:"+direction);     } }

3、編寫享元工廠

package com.weiya.mazhichu.designpatterns.flyweight;

import java.util.HashMap;
import java.util.Map;

/**
 * 
 * 功能:享元工廠
 * 

 *  * @author Moore  * @ClassName Soldier fly weight factory.  * @Version V1.0.  * @date 2019.09.03 21:06:58  */ public class SoldierFlyWeightFactory {     //工廠實(shí)例     private static SoldierFlyWeightFactory INSTANCE;     // 享元池     private static Map soldierMap = new HashMap();     private SoldierFlyWeightFactory(){         SoldierFlyweight normalSoldier = new ConcreteSoliderFlyweight("normal");         soldierMap.put("normal",normalSoldier);         SoldierFlyweight superSolider = new ConcreteSoliderFlyweight("super");         soldierMap.put("super",superSolider);     }     /**      *       * 功能:獲取工廠實(shí)例      * 

     *      * @return soldier fly weight factory      * @author Moore      * @date 2019.09.03 21:07:02      */     public static SoldierFlyWeightFactory getInstance(){         if(INSTANCE == null){             INSTANCE = new SoldierFlyWeightFactory();             return INSTANCE;         }         return INSTANCE;     }     /**      *       * 功能:獲取享元對(duì)象      * 

     *      * @param soliderType :      * @return soldier flyweight      * @author Moore      * @date 2019.09.03 21:07:02      */     public SoldierFlyweight getSolider(String soliderType){         return soldierMap.get(soliderType);     }     /**      *       * 功能:獲取享元池對(duì)象數(shù)量      * 

     *      * @return int      * @author Moore      * @date 2019.09.03 21:07:02      */     public int getSoliderSize(){         return soldierMap.size();     } }

4、客戶端測(cè)試

package com.weiya.mazhichu.designpatterns.flyweight;

/**
 * 
 * 功能:
 * 

 *  * @author Moore  * @ClassName Honour of kings test.  * @Version V1.0.  * @date 2019.09.03 21:06:44  */ public class HonourOfKingsTest {     public static void main(String[] args) {         System.out.println("敵軍還有五秒到達(dá)戰(zhàn)場(chǎng)!");         SoldierFlyWeightFactory factory = SoldierFlyWeightFactory.getInstance();         SoldierFlyweight soldier1 = factory.getSolider("normal");         SoldierFlyweight soldier2 = factory.getSolider("normal");         SoldierFlyweight soldier3 = factory.getSolider("normal");         soldier1.attack("上路");         soldier2.attack("中路");         soldier3.attack("下路");         System.out.println(soldier1 == soldier2);         System.out.println(soldier2 == soldier3);         System.out.println("--------------------------");         System.out.println("主宰已被擊敗!");         SoldierFlyweight soldier4 = factory.getSolider("super");         SoldierFlyweight soldier5 = factory.getSolider("super");         SoldierFlyweight soldier6 = factory.getSolider("super");         soldier4.attack("上路");         soldier5.attack("中路");         soldier6.attack("下路");         System.out.println("對(duì)方法師殘血,被超級(jí)兵打死...");         System.out.println(soldier4 == soldier5);         System.out.println(soldier5 == soldier6);         System.out.println("--------------------------");         System.out.println("該案例一共生成對(duì)象:">

查看運(yùn)行結(jié)果:

Java的享元模式是什么

可以看出,我們一共派出了6個(gè)小兵,其中3個(gè)普通兵,3個(gè)超級(jí)兵,但是享元池中只有兩個(gè)對(duì)象(一個(gè)普通兵、一個(gè)超級(jí)兵對(duì)象),也就是說,無(wú)論派出多少普通兵或者超級(jí)兵,無(wú)論它們要從哪一路出擊,都不會(huì)影響兵的內(nèi)部狀態(tài),從而讓整個(gè)系統(tǒng)的對(duì)象大大減少,減少內(nèi)存消耗,不卡就不影響游戲體驗(yàn),小學(xué)生又可以開心快樂的出來(lái)坑人了,但是要以學(xué)業(yè)為重哦!

享元模式擴(kuò)展

在上面的實(shí)例中,我們主要講的是具體的享元對(duì)象,也就是所有的享元對(duì)象都是必須共享的。但是享元模式的四個(gè)角色中還有一個(gè)非共享的享元實(shí)現(xiàn)對(duì)象,什么意思呢,顧名思義就是享元對(duì)象不一定要共享,但是它通常是作為享元對(duì)象的組合對(duì)象來(lái)使用。從這個(gè)層面來(lái)說,我們又把享元對(duì)象分為:

  • 單純享元模式:在單純享元模式中,所有的享元對(duì)象都是可以共享的,即所有抽象享元類的子類都可共享,不存在非共享具體享元類。

  • 復(fù)合享元模式:將一些單純享元使用組合模式加以組合,可以形成復(fù)合享元對(duì)象,這樣的復(fù)合享元對(duì)象本身不能共享,但是它們可以分解成單純享元對(duì)象,而后者則可以共享。(復(fù)合的享元對(duì)象實(shí)現(xiàn)了抽象享元類,它的實(shí)例就是非共享的享元實(shí)現(xiàn)對(duì)象)

復(fù)合享元模式中,組成復(fù)合享元對(duì)象的每個(gè)單純享元對(duì)象擁有自己的內(nèi)部狀態(tài),而每個(gè)單純享元對(duì)象的外部狀態(tài)都和復(fù)合享元對(duì)象的外部狀態(tài)相同。所以復(fù)合享元模式可以對(duì)多個(gè)單純享元對(duì)象設(shè)置相同的外部狀態(tài), 這也是復(fù)合享元模式的應(yīng)用場(chǎng)景。

單純的享元模式我就不再贅述了,看上面的棋子或者農(nóng)藥的實(shí)例,下面主要說一下組合享元模式,以及它為何非共享,來(lái)看代碼:

1、編寫復(fù)合享元角色類

package com.weiya.mazhichu.designpatterns.flyweight;

import java.util.HashMap;
import java.util.Map;

/**
 * 
 * 功能: 復(fù)合享元角色類(非共享享元實(shí)現(xiàn)對(duì)象)
 * 

 *  * @author Moore  * @ClassName Concrete composite solider flyweight.  * @Version V1.0.  * @date 2019.09.04 10:56:11  */ public class ConcreteCompositeSoliderFlyweight implements SoldierFlyweight {     private static Map soldierMap = new HashMap();     /**      *       * 功能: 增加單純享元對(duì)象      * 

     *      * @param soliderType :      * @param flyweight   :      * @author Moore      * @date 2019.09.04 10:56:11      */     public void add(String soliderType,SoldierFlyweight flyweight){         soldierMap.put(soliderType,flyweight);     }     /**      *       * 功能: flyWeights是單純享元對(duì)象的集合,它們具有相同的外部狀態(tài)extrinsicState,      *     調(diào)用的時(shí)候使用循環(huán)調(diào)用單純享元對(duì)象的attack方法      * 

     *      * @param direction :      * @author Moore      * @date 2019.09.03 21:06:52      */     @Override     public void attack(String direction) {         SoldierFlyweight flyweight = null;         for(String str : soldierMap.keySet()){             flyweight = soldierMap.get(str);             flyweight.attack(direction);         }     }     /**      * 移除單純享元對(duì)象.      * @param soliderType      */     private void remove(String soliderType) {         soldierMap.remove(soliderType);     } }

2、修改后的享元工廠角色類

package com.weiya.mazhichu.designpatterns.flyweight;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 
 * 功能:享元工廠
 * 

 *  * @author Moore  * @ClassName Soldier fly weight factory.  * @Version V1.0.  * @date 2019.09.03 21:06:58  */ public class SoldierFlyWeightFactory {     //工廠實(shí)例     private static SoldierFlyWeightFactory INSTANCE;     // 享元池     private static Map soldierMap = new HashMap();     private SoldierFlyWeightFactory(){         SoldierFlyweight normalSoldier = new ConcreteSoliderFlyweight("normal");         soldierMap.put("normal",normalSoldier);         SoldierFlyweight superSolider = new ConcreteSoliderFlyweight("super");         soldierMap.put("super",superSolider);     }     /**      *       * 功能:獲取工廠實(shí)例      * 

     *      * @return soldier fly weight factory      * @author Moore      * @date 2019.09.03 21:07:02      */     public static SoldierFlyWeightFactory getInstance(){         if(INSTANCE == null){             INSTANCE = new SoldierFlyWeightFactory();             return INSTANCE;         }         return INSTANCE;     }     /**      *       * 功能:獲取享元對(duì)象(單純享元工廠方法)      * 

     *      * @param soliderType :      * @return soldier flyweight      * @author Moore      * @date 2019.09.03 21:07:02      */     public SoldierFlyweight getSolider(String soliderType){         return soldierMap.get(soliderType);     }     /**      *       * 功能:復(fù)合享元工廠方法      * 

     *      * @param compositeSoliderTypes :      * @return soldier flyweight      * @author Moore      * @date 2019.09.04 11:06:24      */     public SoldierFlyweight getCompositeSolider(List compositeSoliderTypes){         ConcreteCompositeSoliderFlyweight compositeFlyweight = new ConcreteCompositeSoliderFlyweight();         for(String soliderType : compositeSoliderTypes){             compositeFlyweight.add(soliderType,this.getSolider(soliderType));         }         return compositeFlyweight;     }     /**      *       * 功能:獲取享元池對(duì)象數(shù)量      * 

     *      * @return int      * @author Moore      * @date 2019.09.03 21:07:02      */     public int getSoliderSize(){         return soldierMap.size();     } }

3、編寫測(cè)試類

package com.weiya.mazhichu.designpatterns.flyweight;

import java.util.ArrayList;
import java.util.List;

/**
 * 
 * 功能: 測(cè)試單純享元模式和復(fù)合享元模式
 * 

 *  * @author Moore  * @ClassName Flyweight test.  * @Version V1.0.  * @date 2019.09.04 11:08:51  */ public class FlyweightTest {     public static void main(String[] args) {         SoldierFlyWeightFactory factory = SoldierFlyWeightFactory.getInstance();         String soliderType = "normal";         SoldierFlyweight soldierFlyweight1 = factory.getSolider(soliderType);         SoldierFlyweight soldierFlyweight2 = factory.getSolider(soliderType);         soldierFlyweight1.attack("上路");         soldierFlyweight2.attack("中路");         System.out.println("---------------------------------");         List compositeSoliderType = new ArrayList();         compositeSoliderType.add("normal");         compositeSoliderType.add("super");         compositeSoliderType.add("normal");         compositeSoliderType.add("super");         compositeSoliderType.add("normal");         SoldierFlyweight compositeSoliderFlyeweight1 = factory.getSolider(compositeSoliderType);         SoldierFlyweight compositeSoliderFlyeweight2 = factory.getSolider(compositeSoliderType);         compositeSoliderFlyeweight1.attack("上路");         compositeSoliderFlyeweight2.attack("中路");         System.out.println("---------------------------------");         System.out.println("單純享元模式是否共享對(duì)象:">

查看運(yùn)行結(jié)果:

Java的享元模式是什么

結(jié)合運(yùn)行結(jié)果,再來(lái)逐字逐句看一下這一段,你應(yīng)該就能有所體會(huì)了。

復(fù)合享元模式中,組成復(fù)合享元對(duì)象的每個(gè)單純享元對(duì)象擁有自己的內(nèi)部狀態(tài),而每個(gè)單純享元對(duì)象的外部狀態(tài)都和復(fù)合享元對(duì)象的外部狀態(tài)相同。所以復(fù)合享元模式可以對(duì)多個(gè)單純享元對(duì)象設(shè)置相同的外部狀態(tài), 這也是復(fù)合享元模式的應(yīng)用場(chǎng)景。

復(fù)合享元模式UML圖

享元模式總結(jié)

使用場(chǎng)景

  • 系統(tǒng)有大量相似或者相同對(duì)象。由于這類對(duì)象的大量使用,造成內(nèi)存的大量耗費(fèi)。

  • 需要緩沖池的場(chǎng)景,(享元池,也就是在需要多次使用享元對(duì)象的時(shí)候)。

  • 對(duì)象的大部分狀態(tài)都可以外部化,可以將這些外部狀態(tài)傳入對(duì)象中。

優(yōu)點(diǎn)

  • 大大減少對(duì)象的創(chuàng)建,降低系統(tǒng)的內(nèi)存,使效率提高。

  • 享元模式的外部狀態(tài)相對(duì)獨(dú)立,而且不會(huì)影響其內(nèi)部狀態(tài),從而使得享元對(duì)象可以在不同的環(huán)境中被共享。

缺點(diǎn)

  • 需要分離出外部狀態(tài)和內(nèi)部狀態(tài),提高了系統(tǒng)的復(fù)雜度。

  • 讀取享元模式的外部狀態(tài)會(huì)使得運(yùn)行時(shí)間稍微變長(zhǎng)。

到此,相信大家對(duì)“Java的享元模式是什么”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!


分享標(biāo)題:Java的享元模式是什么
分享路徑:http://weahome.cn/article/ghgspe.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部