天天看點

設計模式之享元模式(Flyweight Pattern)總結

What:

使用共享的方式高效的支援大量的細粒度的對象。

Why:

優點:

1.減少建立的對象數量,減少記憶體占用和提高性能;

2.享元模式的外部狀态相對獨立,而且不會影響其内部狀态,進而使得享元對象可以在不同的環境中被共享。

缺點:

1.享元模式使得系統更加複雜,需要分離出内部狀态和外部狀态,這使得程式的邏輯複雜化;

2.為了使對象可以共享,享元模式需要将享元對象的狀态外部化,而讀取外部狀态使得運作時間變長。

Where:

1、系統有大量相似對象。

2、需要緩沖池的場景。

How:

在學習使用享元模式之前,我們需要先了解幾個角色。

FlyWeight:定義共享對象的功能。

ConcreteFlyWeight:共享對象的具體實作。

FlyWeightFactory:封裝共享對象工廠。

設計模式之享元模式(Flyweight Pattern)總結

示例:以王者榮耀的角色建立為例,通過建立角色的過程進一步體會享元模式。(FlyWeight接口并非一定需要,分了簡便Demo中省略)

Hero類:英雄的屬性

public class Hero {

    private String heroClass;//英雄職業

    private String name;//角色名字

    private long attack;//攻擊力

    private long defence;//防禦力

    public Hero() {
    }

    //省略get、set方法
    
    public void create() {
        System.out.println("職業:" + this.getHeroClass() + "\n"
                + "建立的角色:" + this.getName() + "\n"
                + "角色屬性:" + "\n"
                + "攻擊力:" + this.getAttack() + "\n"
                + "防禦力:" + this.getDefence() + "\n");
    }
}
           

HeroFactory類:建立英雄的工廠

public class HeroFactory {

    public HashMap<String,Hero> map = new HashMap();

    public Hero factory(String heroClass){
        Hero hero = map.get(heroClass);
        if(hero == null){
            hero = new Hero();
            map.put(heroClass,hero);
        }
        return hero;
    }
}
           

Test類:測試類

public class Test {
    public static void main(String[] args) {
        HeroFactory heroFactory = new HeroFactory();

        String fashi = "法師";
        String sheshou = "射手";

        Hero hero1 = heroFactory.factory(fashi);
        hero1.setHeroClass(fashi);
        hero1.setName("王昭君");
        hero1.setAttack(1000);
        hero1.setDefence(100);
        hero1.create();


        Hero hero2 = heroFactory.factory(fashi);
        hero2.setHeroClass(fashi);
        hero2.setName("嬴政");
        hero2.setAttack(1200);
        hero2.setDefence(180);
        hero2.create();


        Hero hero3 = heroFactory.factory(sheshou);
        hero3.setHeroClass(sheshou);
        hero3.setName("後裔");
        hero3.setAttack(1500);
        hero3.setDefence(100);
        hero3.create();

        System.out.println("輸出各對象的位址:");
        System.out.println(hero1);
        System.out.println(hero2);
        System.out.println(hero3);
    }
}
           

輸出結果:

職業:法師
建立的角色:王昭君
角色屬性:
攻擊力:1000
防禦力:100

職業:法師
建立的角色:嬴政
角色屬性:
攻擊力:1200
防禦力:180

職業:射手
建立的角色:後裔
角色屬性:
攻擊力:1500
防禦力:100

輸出各對象的位址:
FlyweightPattern.Hero@4554617c
FlyweightPattern.Hero@4554617c
FlyweightPattern.Hero@74a14482
           

總結

通過輸出的對象位址可知,同一職業的英雄對象不會重複建立。也就是說,在享元模式下,可以避免重複建立相同或者相似的對象,這樣可以減少記憶體和提高程式的效率。

了解更多設計模式:

設計模式系列

參考資料:

《大話設計模式》

https://www.runoob.com/design-pattern/flyweight-pattern.html

http://c.biancheng.net/view/1371.html