1. 程式人生 > >設計模式之——享元設計模式

設計模式之——享元設計模式

享元模式(Flyweight Pattern)主要用於減少建立物件的數量,以減少記憶體佔用和提高效能。這種型別的設計模式屬於結構型模式,它提供了減少物件數量從而改善應用所需的物件結構的方式。享元模式嘗試重用現有的同類物件,如果未找到匹配的物件,則建立新物件。所以其核心就是控制類中要有一個HashMap儲存已經建立的物件。

以農藥中的英雄為例吧:

定義英雄的通用行為

package com.zndroid.dm.FlyweightModel;

/**
 * Created by luzhenyu on 2017/9/6.
 */

/**定義英雄通用的行為*/
public interface IHeroCommon {
    //英雄行為:釋放技能以及物理攻擊
    String releaseKills(int killIndex);
    String commonAttack();
}

抽象出英雄通用操作

package com.zndroid.dm.FlyweightModel;

/**
 * Created by luzhenyu on 2017/9/6.
 */

/**抽象英雄基類,並規則化可共享以及不可共享的部分*/
public abstract class BaseHero implements IHeroCommon {
    protected String name;//英雄名字
    protected String[] kills;

    public BaseHero() {
        kills = initKills();
        name = getName();
        checkKills();
    }

    private void checkKills() {
        if (kills.length <= 0 && kills.length > 3)
            return;//王者榮耀最多三個技能吧
    }

    //每個英雄技能以及名字不共享
    public abstract String[] initKills();
    public abstract String getName();
    public abstract String passiveKill();//被動技能

    //但是釋放技能是共享,每個英雄大同小異
    @Override
    public String releaseKills(int killIndex) {
        return  name + " release " + kills[killIndex] + " + 被動 " + passiveKill() + " biu biu biu ~ ";
    }

    @Override
    public String commonAttack() {
        return name + " release 物理攻擊 kua kua kua ~";
    }
}

下面是具體的英雄實現

package com.zndroid.dm.FlyweightModel.impl;

import com.zndroid.dm.FlyweightModel.BaseHero;

/**
 * Created by luzhenyu on 2017/9/6.
 */

public class Arthur extends BaseHero {
    @Override
    public String[] initKills() {
        return new String[]{"誓約之盾", "迴旋打擊", "聖劍裁決"};
    }

    @Override
    public String getName() {
        return "亞瑟";
    }

    @Override
    public String passiveKill() {
        return "聖光守護";
    }
}
package com.zndroid.dm.FlyweightModel.impl;

import com.zndroid.dm.FlyweightModel.BaseHero;

/**
 * Created by luzhenyu on 2017/9/6.
 */

public class HouYi extends BaseHero {
    @Override
    public String[] initKills() {
        return new String[]{"炙熱之風", "燎原箭雨", "懲戒射擊"};
    }

    @Override
    public String getName() {
        return "后羿";
    }

    @Override
    public String passiveKill() {
        return "遲緩之箭";
    }
}
package com.zndroid.dm.FlyweightModel.impl;

import com.zndroid.dm.FlyweightModel.BaseHero;

/**
 * Created by luzhenyu on 2017/9/6.
 */

public class ZhuGeLiang extends BaseHero {
    @Override
    public String[] initKills() {
        return new String[]{"東風破襲", "時空穿梭", "元氣彈"};
    }

    @Override
    public String getName() {
        return "諸葛亮";
    }

    @Override
    public String passiveKill() {
        return "策謀之刻";
    }
}

核心在這,儲存/新建英雄

package com.zndroid.dm.FlyweightModel;

import com.zndroid.dm.FlyweightModel.impl.Arthur;
import com.zndroid.dm.FlyweightModel.impl.HouYi;
import com.zndroid.dm.FlyweightModel.impl.ZhuGeLiang;

import java.util.HashMap;

/**
 * Created by luzhenyu on 2017/9/6.
 */

public class HeroManager {
    private HashMap<String, BaseHero> map;

    private HeroManager(){
        map = new HashMap<>();
    }

    private static HeroManager manager = new HeroManager();
    public static HeroManager getManager() {
        return manager;
    }

    public BaseHero createHero(String name) {
        BaseHero hero = map.get(name);//用唯一標識碼判斷,如果在記憶體中有,則返回這個唯一標識碼所標識的物件
        if (null == hero) {
            switch (name){

                case "亞瑟":
                    hero =  new Arthur();
                    break;
                case "諸葛亮":
                    hero = new ZhuGeLiang();
                    break;
                case "后羿":
                    hero = new HouYi();
                    break;
            }
            map.put(name, hero);
        }

        System.out.println("(這條訊息請忽略:) " + name + "[" + hero.toString() + "]");
        return hero;
    }

}

下面建立玩家:

package com.zndroid.dm.FlyweightModel.user;

/**
 * Created by luzhenyu on 2017/9/6.
 */

import com.zndroid.dm.FlyweightModel.BaseHero;
import com.zndroid.dm.FlyweightModel.impl.HouYi;

/**來表示玩家*/
public class Role {

    private long MP;
    private long HP;
    private String niceName;

    private BaseHero hero;

    public long getMP() {
        return MP;
    }

    public void setMP(long MP) {
        this.MP = MP;
    }

    public long getHP() {
        return HP;
    }

    public void setHP(long HP) {
        this.HP = HP;
    }

    public String getNiceName() {
        return niceName;
    }

    public void setNiceName(String niceName) {
        this.niceName = niceName;
    }

    public Role(BaseHero hero) {
        this.hero = hero;
    }

    public void releaseKill(int index) {
        System.out.println(getNiceName() + " use " + hero.releaseKills(index));
    }

    public void releaseCommonAttack() {
        System.out.println(getNiceName() + " use " + hero.commonAttack());
    }
}

來看一下使用:

/**
         * 享元模式
         * 它使用共享物件,用來儘可能減少記憶體使用量以及分享資訊給儘可能多的相似物件;
         * 它適合用於當大量物件只是重複因而導致無法令人接受的使用大量記憶體。通常物件中的部分狀態是可以分享。
         * 常見做法是把它們放在外部資料結構,當需要使用時再將它們傳遞給享元。
         * 把一個物件可共享的狀態給封裝起來,而不可能共享的狀態則從外部獲取,享元模式嘗試重用現有的同類物件,如果未找到匹配的物件,則建立新物件
         * 用唯一標識碼判斷,如果在記憶體中有,則返回這個唯一標識碼所標識的物件(用 HashMap 儲存這些物件)。
         * 應用例項:JAVA 中的 String,資料庫中的資料池
         * 使用場景: 1、系統有大量相似物件。 2、需要緩衝池的場景。
         * 注意事項: 1、注意劃分外部狀態和內部狀態,否則可能會引起執行緒安全問題。 2、這些類必須有一個工廠物件加以控制。
         * */

        //現在王者榮耀辣麼火,同一個伺服器辣麼多人,玩同一角色的玩家也是非常多的,假如說有100個玩家玩亞瑟,那麼遊戲需要建立100個亞瑟
        //分配給這100個玩家,如果10000個  1000000個呢? 想想就可怕, 明明就是同一個亞瑟這個英雄拿哪來這麼多物件啊,多的也就是玩家,但是英雄不應該也這麼多啊。
        //這樣同一個伺服器記憶體肯定吃不消,因此,享元模式可以解決這個問題,不就是同一個亞瑟嗎,他們的基礎屬性(內部,不共享)都是一樣的,區別在於玩家的血量不一樣(外部共享)以及
        //玩家釋放具體技能不一樣(但是每個技能的效果亞瑟肯定都是一樣的,具體釋放哪個技能交給玩家決定好了)

        //匹配中...
        HeroManager manager = HeroManager.getManager();

        /**藍方隊伍*/
        //玩家1進入,並選擇英雄
        Role bRole1 = new Role(manager.createHero("后羿"));
        bRole1.setHP(1000);
        bRole1.setMP(1500);
        bRole1.setNiceName("藍隊玩家1");

        //玩家2進入,並選擇英雄
        Role bRole2 = new Role(manager.createHero("亞瑟"));
        bRole2.setHP(0);
        bRole2.setMP(2500);
        bRole2.setNiceName("藍隊玩家2");

        //玩家3進入,並選擇英雄
        Role bRole3 = new Role(manager.createHero("諸葛亮"));
        bRole3.setHP(1500);
        bRole3.setMP(2000);
        bRole3.setNiceName("藍隊玩家3");

        //......
        /**紅方隊伍*/
        //玩家1進入,並選擇英雄
        Role rRole1 = new Role(manager.createHero("后羿"));
        rRole1.setHP(1000);
        rRole1.setMP(1500);
        rRole1.setNiceName("紅隊玩家1");

        //玩家1進入,並選擇英雄
        Role rRole2 = new Role(manager.createHero("諸葛亮"));
        rRole2.setHP(1500);
        rRole2.setMP(2000);
        rRole2.setNiceName("紅隊玩家2");

        //玩家1進入,並選擇英雄
        Role rRole3 = new Role(manager.createHero("亞瑟"));
        rRole3.setHP(0);
        rRole3.setMP(2500);
        rRole3.setNiceName("紅隊玩家3");

        ////// 敵軍還有5秒鐘到達戰場... //////
        // 以下是酣暢淋漓的戰鬥
        bRole1.releaseKill(1);
        bRole1.releaseCommonAttack();

        rRole3.releaseKill(1);
        rRole3.releaseCommonAttack();

        rRole2.releaseKill(2);

        bRole2.releaseCommonAttack();
        bRole2.releaseKill(0);

        rRole1.releaseCommonAttack();
        rRole1.releaseKill(0);

        bRole3.releaseKill(2);
        // ACE
        // 6分投吧~~~~
        log("----------------我是分割線-----------------");

執行結果:

[ ======================================== ]
(這條訊息請忽略:) 后羿[[email protected]]
(這條訊息請忽略:) 亞瑟[[email protected]]
(這條訊息請忽略:) 諸葛亮[[email protected]]
(這條訊息請忽略:) 后羿[[email protected]]
(這條訊息請忽略:) 諸葛亮[[email protected]]
(這條訊息請忽略:) 亞瑟[[email protected]]
藍隊玩家1 use 后羿 release 燎原箭雨 + 被動 遲緩之箭 biu biu biu ~
藍隊玩家1 use 后羿 release 物理攻擊 kua kua kua ~
紅隊玩家3 use 亞瑟 release 迴旋打擊 + 被動 聖光守護 biu biu biu ~
紅隊玩家3 use 亞瑟 release 物理攻擊 kua kua kua ~
紅隊玩家2 use 諸葛亮 release 元氣彈 + 被動 策謀之刻 biu biu biu ~
藍隊玩家2 use 亞瑟 release 物理攻擊 kua kua kua ~
藍隊玩家2 use 亞瑟 release 誓約之盾 + 被動 聖光守護 biu biu biu ~
紅隊玩家1 use 后羿 release 物理攻擊 kua kua kua ~
紅隊玩家1 use 后羿 release 炙熱之風 + 被動 遲緩之箭 biu biu biu ~
藍隊玩家3 use 諸葛亮 release 元氣彈 + 被動 策謀之刻 biu biu biu ~
[ ----------------我是分割線----------------- ]
[ ======================================== ]



【歡迎上碼】

【微信公眾號搜尋 h2o2s2】


相關推薦

設計模式——設計模式

享元模式(Flyweight Pattern)主要用於減少建立物件的數量,以減少記憶體佔用和提高效能。這種型別的設計模式屬於結構型模式,它提供了減少物件數量從而改善應用所需的物件結構的方式。享元模式嘗試重用現有的同類物件,如果未找到匹配的物件,則建立新物件。所以其核心就是控

java設計模式設計模式

一.構成 單純享元模式 抽象享元角色:定義了公共的介面,所有的具體享元角色需要實現的介面,那些需要外蘊狀態的操作可以通過方法的引數傳入.具體享元角色:實現抽線享元角色所規定的公共介面,如果有內蘊狀態

java設計模式模式

並不是 計算 lov 這一 返回 實例 map() 角色 ron 當前咱們國家正在大力倡導構建和諧社會,其中一個很重要的組成部分就是建設資源節約型社會,“浪費可恥,節儉光榮”。在軟件系統中,有時候也會存在資源浪費的情況,例如在計算機內存中存儲了多個完全相同或者非常相似的

Head First設計模式模式(蠅量模式

logs sign face isp ria reat 定義 ogr sans 一、定義 享元模式(Flyweight Pattern)主要用於減少創建對象的數量,以減少內存占用和提高性能。這種類型的設計模式屬於結構型模式,它提供了減少對象數量從而改善應用所需的對象結構的

Java設計模式模式實例詳解

AI ava flyweight lan trac home erro lin 代碼 本文實例講述了Java設計模式之享元模式。分享給大家供大家參考,具體如下: 解釋一下概念:也就是說在一個系統中如果有多個相同的對象,那麽只共享一份就可以了,不必每個都去實例化一個對象。比如

設計模式---對象性能模式模式(Flyweight)

ret 大量 根據 利用 問題 字母 只讀 時代 帶來 一:概念 通過與其他類似對象共享數據來減少內存占用 如果一個應用程序使用了太多的對象, 就會造成很大的存儲開銷。 特別是對於大量輕量級 (細粒度)的對象,比如在文檔編輯器的設計過程中,我們如果為每個字母

設計模式的藝術 結構性模式模式

前言 知道圍棋的都知道圍棋有兩種顏色的棋子,黑色和白色,不同的地方就在於他們所放置的位置不同,大體是一樣的,所以廠家生產的時候也就是批量的進行生產,反正棋子放哪他們並不需要操心,在計算機中也會存在著很多相似的物件,如果相同的物件太多將導致系統執行代價過高,記憶體屬於計算機稀缺資源,不能隨便浪費,

設計模式模式(蠅量模式

設計模式之享元模式(蠅量模式) 1. 什麼是享元模式 Flyweight模式也叫享元模式,是構造型模式之一,它通過與其他類似物件共享資料來減小記憶體佔用。 換句話說就是通過共享的方式高效地支援大量細粒度的物件。 享元模式的結構: 享元模式的角色和職責:

設計模式模式(Flyweight)

設計模式之享元模式(Flyweight) 本篇為https://github.com/iluwatar/java-design-patterns/tree/master/flyweight閱讀筆記 場景 煉金術士的商店裡擺滿了魔法藥水。許多藥水是相同的,因此不需要為每

設計模式 模式

info 如果能 實例化 應用 技術 一個 對象存儲 數量 col (一) 享元模式   享元模式 : 運用共享技術有效地支持大量細粒度的對象    (二)內部狀態和外部狀態   在享元對象內部並且不會隨環境改變而改變的共享部分,可以稱為是享元對象的內部狀態,而隨環

設計模式模式(Flyweight Pattern)

目的:主要用於減少建立物件的數量,以減少記憶體佔用和提高效能。 應用例項: 1、JAVA 中的 String,如果有則返回,如果沒有則建立一個字串儲存在字串快取池裡面。 2、資料庫的資料池。 程式碼: 畫圖形的 介面,描述畫這個動作: public interface Shape {

設計模式模式(C++)

設計模式之享元模式 享元模式,運用共享技術有效地支援大量細粒度的物件。面向物件技術可以很好地解決一些靈活性或擴充套件性問題,但在很多情況下需要在系統中增加類和物件的個數。當物件數量太多時,將導致執行代價過高,帶來效能下降等問題。享元模式正式為了解決這依賴問題而誕

設計模式模式

享元模式定義 享元模式(Flyweight Pattern)是池技術的重要實現方式,使用共享物件可有效地支援大量的細粒度的物件。 通用類圖 具體實現 當應用程式中存在大量的物件時,程式的效能會有所下降,而且可能會造成記憶體溢位。這時除了增加硬體資源或者借用

每天一個設計模式模式

作者按:《每天一個設計模式》旨在初步領會設計模式的精髓,目前採用javascript和python兩種語言實現。誠然,每種設計模式都有多種實現方式,但此小冊只記錄最直截了當的實現方式 :) 個人技術部落格-godbmw.com 歡迎來玩! 每週至少 1 篇原創技術分享,還有開源教程(webpack

23種設計模式模式

享元模式的定義 定義: 使用共享物件可有效的支援大量的細粒度的物件 通俗的說, 就是將類的通用屬性抽出來,建立物件池,以達到限制物件數量的效果 上面定義中要求細粒度物件, 那麼不可避免的使得物件數量多且性質相近, 我們將這些物件的資訊分為兩個部分: 內部狀態和外部狀態 內部狀態是物件可以共享出來

設計模式模式(結構型)

程序 aid 共享 對象 ron map 內部 系統 抽象 模式定義 享元模式(Flyweight Pattern)就是通過共享技術實現大量細粒度對象的復用。享元模式是通過細粒度對象的共享,所以也可以說享元模式是一種輕量級模式。按照Gof模式分類,享元模式屬於對象結構型模式

設計模式模式(卷十一)

通過使用池的技術,有效減少了大量細粒度的物件的重複生成。 0x00 組織結構 Flyweight:抽象享元類,聲明瞭可以想外界提供內部狀態的方法,同時還可以設定外部狀態。 ConcreteFlyweight:具體享元類,通常和單例模式組合使用。 U

C#--設計模式模式

這幾天專案比較忙,感覺已經隔了半個世紀沒來園裡轉了,接著上次的設計模式來繼續說吧,這會來敘說一下享元模式,首先應用場景:就是在  我們需要重複使用某個物件的時候,如果我們重複地使用new建立這個物件的話,這樣我們在記憶體就需要多次地去申請記憶體空間了,這樣可能會出現記憶

設計模式模式(2)

本質 分離與共享。 程式碼示例 (1)定義描述授權資料的享元介面 package flyWeight; public interface FlyWeight { public b

23種設計模式模式(結構型,7 Flyweight,c++實現)

程式碼實現:#include<iostream>#include<list>#include<string>#include<map>usingnamespace std;classPerson{public:Person(st