版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、Java設(shè)計模式論文完成人班級學(xué)號設(shè)計模式在游戲設(shè)計中的應(yīng)用1. 程序設(shè)計目標(biāo)與使用說明1.1前言設(shè)計模式在軟件工程中有著廣泛的應(yīng)用,如java的MVC框架,用到了Observer模式,c#的LINQ,用到了Iterator模式,甚至連c+的STL中Iterator模式都有廣泛的應(yīng)用,但是我對這些軟件工程方面的應(yīng)用不是很感興趣,我感興趣的是設(shè)計模式在游戲開發(fā)中的應(yīng)用,因此我嘗試著使用Strategy模式和Abstract Factory模式來設(shè)計一個角色扮演游戲,來體驗設(shè)計模式在游戲開發(fā)中的優(yōu)勢之處,由于我更善于使用c#編程,因此游戲?qū)⒁詂#為基礎(chǔ),代碼運(yùn)行環(huán)境是VS2010。我始終覺得,設(shè)計
2、模式的作用是為了方便開發(fā),如果因為設(shè)計模式而使得開發(fā)變得復(fù)雜,那就得不償失了,當(dāng)然由于水平有限,我所能涉及到的只是游戲與設(shè)計模式應(yīng)用的冰山一角,更深入的知識,需要我在以后的學(xué)習(xí)中不斷的去深入和探究。1.2工程說明工程開發(fā)環(huán)境是vs2010 32位旗艦中文版,項目是c#控制臺應(yīng)用程序。打開項目需要先打開電子檔中的RpgGame文件夾,雙擊RpgGame.sln打開打開工程后,具體的源代碼在Program.cs中:2. 游戲具體實現(xiàn)在游戲開發(fā)的開始,我設(shè)定構(gòu)建一個魔法世界的游戲,游戲中的角色有魔法師、戰(zhàn)士、牧師三種職業(yè),人物有人類、精靈兩種種族。三種職業(yè)需要施展不同的魔法,因此需要用Strateg
3、y模式將角色行為和技能施展分離開來;而兩個種族由于有著大同小異的外形,所以可以用Abstract Factory模式提煉出抽象的“身體”和具體的人類和精靈的實現(xiàn)。2.1.角色技能與Strategy模式1) 繼承實現(xiàn)的問題在開始游戲之前,我為玩家設(shè)定三種職業(yè):魔法師、戰(zhàn)士、牧師。正如字面上所看到的,魔法師擅長使用魔法攻擊,戰(zhàn)士擅長使用物理攻擊,而牧師則擅長治療。根據(jù)面向?qū)ο缶幊趟枷耄倚枰榷x一個抽象類作為基類,將三個職業(yè)的實現(xiàn)作為子類,以實現(xiàn)代碼的重用。對于抽象基類來說,首先要確定的是角色應(yīng)該擁有的獨立于職業(yè)的能力:Ø ShowInfo():顯示角色基本信息,如魔法師顯示:This
4、 is a magician.Ø Run():讓角色行走,顯示:Player is running.Ø Stay():讓角色站立,顯示:Player is standing.一般來說,設(shè)計時需要遵循這樣的原則:1. 對于所有繼承類都有,但是每個繼承類的實現(xiàn)各不相同的方法,我們在基類中只給出定義,不給出實現(xiàn),而在繼承類中予以實現(xiàn)。換言之,就是在基類中定義一個抽象方法。2. 對于所有繼承類都有,并且每個繼承類的實現(xiàn)完全相同的方法,我們直接在基類中實現(xiàn)它,而由子類去繼承,以實現(xiàn)代碼重用。很顯然,每個職業(yè)都擁有上邊定義的三種能力,其中ShowInfo()對于每種職業(yè)都不相同,而Ru
5、n()和Stay()對于每種職業(yè)都相同,于是構(gòu)建基類,實現(xiàn)下面的UML設(shè)計:2) 基類實現(xiàn)和繼承實現(xiàn)的問題實現(xiàn)基本功能后,考慮讓所有的職業(yè)可以實現(xiàn)技能的釋放,因此需要添加一個新的方法ReleaseSkills(),很容易想到的是在基類Charactor中添加方法ReleaseSkills(),這樣可以實現(xiàn)代碼的重用,但是很容易就可以發(fā)現(xiàn)三個子類釋放技能的方式并不相同,將方法放在基類中不但沒有解決問題,反而使問題復(fù)雜了,將問題抽象化,可以得到這樣的描述:給基類添加實體方法,使得不應(yīng)該擁有此方法的子類也擁有了此方法,也使得所有子類方法擁有了完全一樣的實現(xiàn)。當(dāng)然可以有另外一種解決的方法,那就是在每個
6、子類中定義各自的ReleaseSkills()覆蓋基類的方法,這樣似乎解決了問題,但如果有一天需要加入一個新的職業(yè),比如騎士,那就需要重新定義它的ReleaseSkills(),這樣的缺陷顯而易見:v 沒有實現(xiàn)代碼重用,如果新添加角色的話,就需要重新寫代碼進(jìn)行覆蓋。v 如果釋放技能的方法需要改動,那么就不得不在子類中都重新寫一遍。v 如果新定義一種職業(yè)不需要釋放技能,但是它也繼承了ReleaseSkills()的方法,即使在子類中定義一個空的ReleaseSkills()方法,仍然會暴露出它擁有ReleaseSkills()的能力。3) 引入接口繼承的使用會帶來很多問題,那么嘗試使用接口來實現(xiàn)
7、。首先定義ReleaseSkills()接口,然后在子類中實現(xiàn)。當(dāng)然這里沒有考慮戰(zhàn)士釋放技能的問題,事實上戰(zhàn)士一般是不需要釋放技能的能力的。由此我們得到下面的UML圖:使用接口雖然解決了部分問題,但是有更多的問題沒有解決,例如,子類仍然要重新寫自己的釋放技能的實現(xiàn)代碼,所以為了使釋放技能與角色本身分離開來,就需要將釋放技能的接口封裝起來。4) 封裝行為面向?qū)ο蟮囊粋€原則是封裝變化,在當(dāng)前的情況中,ReleaseSkills()這個行為是不斷變化的,那么在設(shè)計的過程中我就需要想辦法將它封裝起來。實現(xiàn)此接口的類不再是定義的角色的基類或者子類,而是專用于ReleaseSkills()這個行為的類。如
8、下圖所示:在這里,接口的實現(xiàn)放在了它自己的繼承體系中,而不是放到角色類里邊,每一個實現(xiàn)接口的類完成一個特定的ReleaseSkills()的實現(xiàn),比如ReleaseMagic類打印一句:Magic has been released,ReleaseLight類(光系魔法,也就是治療魔法)打印一句:Light has been released,而ReleaseNothing類對應(yīng)不釋放魔法的戰(zhàn)士,打印一句:I cant release magic。下面要做的就是將這個技能釋放的體系與角色體系結(jié)合起來,具體就是在基類中聲明Skills類型的變量,如下圖所示:注意到 Character 類中仍有一
9、個ReleaseSkills()方法,但是這個方法與之前的ReleaseSkills()方法不同:² 它不是用來給子類去覆蓋的。² 我們通過Character的ReleaseSkills()方法實際去調(diào)用 Skills 接口的ReleaseSkills()方法(實際上調(diào)用了其實體類的ReleaseSkills()方法)。具體類定義的代碼如下:/定義釋放技能的接口 public interface Skills void ReleaseSkills(); /定義釋放魔法的類 public class ReleaseMagic : Skills public void Rele
10、aseSkills() Console.WriteLine("Magic has been released."); /定義釋放治療的類 public class ReleaseLight : Skills public void ReleaseSkills() Console.WriteLine("Light has been released."); /定義不釋放技能的類 public class ReleaseNothing : Skills public void ReleaseSkills() Console.WriteLine("I
11、 can't release skills."); /角色基類 public abstract class Charactor protected Skills releaseSkills; /釋放技能,通過接口來調(diào)用 public void ReleaseSkills() releaseSkills.ReleaseSkills(); /動態(tài)更改角色的釋放技能能力 public void ChangeSkills(Skills newSkill) Console.WriteLine("I have Changed my skills."); release
12、Skills = newSkill; public void Run() Console.WriteLine("I am Running."); public void Stay() Console.WriteLine("I am standing."); abstract public void ShowInfo(); /顯示角色信息 /定義魔法師 public class Magician : Charactor public Magician() /初始化來自基類的Skills變量 releaseSkills = new ReleaseMagic(
13、); public override void ShowInfo() Console.WriteLine("I am a Magician."); /定義戰(zhàn)士 public class Warrior : Charactor public Warrior() releaseSkills = new ReleaseNothing(); public override void ShowInfo() Console.WriteLine("I am a Warrior."); /定義牧師 public class Priest : Charactor publ
14、ic Priest() releaseSkills = new ReleaseLight(); public override void ShowInfo() Console.WriteLine("I am a Priest."); 到現(xiàn)在可以有一個總結(jié),上邊封裝的Skills接口,實際上使用了Strategy模式,正如Strategy模式的官方定義:Strategy模式定義了一系列的算法,將它們每一個進(jìn)行封裝,并使它們可以相互交換。Strategy模式使得算法不依賴于使用它的客戶端。2.2人物構(gòu)造與 Abstract Factory模式1) 面向?qū)崿F(xiàn)的方式當(dāng)設(shè)定完職業(yè)之后
15、,我需要設(shè)定角色的種族,為了簡單起見,在這里我只設(shè)定了精靈和人類,當(dāng)然如果以后要擴(kuò)展的話,還可以加入矮人、獸人、魔族等種族。對比精靈和人類可以發(fā)現(xiàn)他們的相同和不同之處:l 都有頭部、身軀和四肢,面部都有五官。l 精靈的耳朵、眼睛、皮膚和身材是異于人類的。由此可以假定角色身體由三部分組成:頭部(Head)、身體(Body)、皮膚(Skin)。于是得到下面的設(shè)計:2) 抽象組成身體的實體類我發(fā)現(xiàn)這樣做,每個角色與他的身體部件是牢牢綁定在一起的,每創(chuàng)建一個角色,我都需要為它先行創(chuàng)建所有其復(fù)合的類(組成身體的實體類,比如HumanHead)。按照面向?qū)ο蟮乃枷耄蚁氲綉?yīng)該對這一過程進(jìn)行封裝,將創(chuàng)建角色
16、部件這件事委派給其他的類來完成。觀察上圖,我發(fā)現(xiàn)盡管角色不同,但它們都是由三個部分構(gòu)成,所以,我所能想到的實現(xiàn)這一過程的第一步,就是對組成身體的實體類進(jìn)行抽象,定義三個接口:Head、Body、Skin,代表身體的三個部分,并且讓Human和Elf的實體類去實現(xiàn)這個接口:通過上圖可以發(fā)現(xiàn),發(fā)現(xiàn)盡管定義了接口,但是如果角色Human和Elf仍然與接口的實體類關(guān)聯(lián),那么效果與面向?qū)崿F(xiàn)完全相同。而且還有一個問題是Human與Elf相似的地方很多,除了名字不同其余的完全一樣,那么久可以將它們合并成一個類,起名叫Race(種族),設(shè)計再次變成下面這樣:3) 創(chuàng)建工廠類到這里現(xiàn)在結(jié)構(gòu)已經(jīng)很完善了,我定義了
17、接口來解決問題,也沒有為不同的角色創(chuàng)建多個不同的類,而只要在Race的構(gòu)造函數(shù)中為代表身體部件的變量賦不同的值,就可以創(chuàng)建不同種族的角色。這時候,如果有一個類可以專門負(fù)責(zé)創(chuàng)建身體部件這件事,當(dāng)想要創(chuàng)建角色的時候,將這個類傳遞給Race的構(gòu)造函數(shù)就可以了。設(shè)定創(chuàng)建Human身體組成部分的類稱作:HumanPartsFactory,創(chuàng)建Elf身體部分的類稱作ElfPartsFacotry。那么它們應(yīng)該是這樣的:但是Race的構(gòu)造函數(shù)只能接受一個HumanPartsFactory類型的參數(shù),為了傳遞ElfPartsFactory,將不得不再添加一個接受ElfPartsFactory類型的構(gòu)造函數(shù)。這
18、樣顯然不好,所以應(yīng)該建立一個抽象的種族工廠:4) Abstract Factory設(shè)計模式上面做的這些,使用到了一個新的設(shè)計模式:Abstract Factory。它的正式定義是這樣的:提供一個接口用于創(chuàng)建一系列相互關(guān)聯(lián)或者相互依賴的對象,而不需要指定它們的實體類。最后完整的UML設(shè)計應(yīng)該是這樣子的:下面是代碼實現(xiàn):/定義構(gòu)成身體部分的接口 public interface Head string name get; public interface Body string name get; public interface Skin string name get; /組成human的類
19、public class HumanHead : Head public string name get return "Human Head" public class HumanBody : Body public string name get return "Human Body" public class HumanSkin : Skin public string name get return "Human Skin" /組成Elf的類 public class ElfHead : Head public string
20、name get return "Elf Head" public class ElfBody : Body public string name get return "Elf Body" public class ElfSkin : Skin public string name get return "Elf Skin" /定義工廠接口 public interface RaceFactory Head CreateHead(); Body CreateBody(); Skin CreateSkin(); /定義human的身體
21、工廠類 public class HumanFactory : RaceFactory public Head CreateHead() return new HumanHead(); public Body CreateBody() return new HumanBody(); public Skin CreateSkin() return new HumanSkin(); /定義Elf的身體工廠類 public class ElfFactory : RaceFactory public Head CreateHead() return new ElfHead(); public Body
22、 CreateBody() return new ElfBody(); public Skin CreateSkin() return new ElfSkin(); /定義Race類 public class Race public Head head; public Body body; public Skin skin; public Race(RaceFactory raceFactory) head = raceFactory.CreateHead(); body = raceFactory.CreateBody(); skin = raceFactory.CreateSkin();
23、為了方便的調(diào)用以上定義的技能類和種族類,我需要建立一個Race類來包含上邊兩個類的實現(xiàn),代碼如下: class Player public Charactor career; public Race race; /為玩家初始化 public Player(Charactor charactor, Race playerRace) career = charactor; race = playerRace; 將兩部分設(shè)計模式結(jié)合起來,我們就可以在實際中很方便的應(yīng)用它們,例如如果我想定義一個玩家,職業(yè)是魔法師,種族是精靈,那么可以這樣:/定義一個新的玩家,職業(yè)是魔法師,種族是精靈Player player = new Player(new Magician(), new Race(new ElfFactory();當(dāng)需要展示這個玩家的信息的時候,直接調(diào)用方法就可以了:player.car
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 滬科版九年級數(shù)學(xué)上冊期末復(fù)習(xí)考點 第23章 解直角三角形知識歸納與題型突破(12類題型清單)
- 2024-2030年中國型鋼產(chǎn)業(yè)趨勢預(yù)測及投資產(chǎn)量分析報告
- 2024-2030年中國地鐵建設(shè)行業(yè)前景規(guī)劃及投資經(jīng)營模式分析報告
- 2024年智能軟件使用與數(shù)據(jù)保密協(xié)議2篇
- 2024年特許經(jīng)營合同(加盟)
- 梅河口康美職業(yè)技術(shù)學(xué)院《運(yùn)動傷害事故處理與急救》2023-2024學(xué)年第一學(xué)期期末試卷
- 2024年“通辦”第二批事項指導(dǎo)目錄實施合同范本3篇
- 2024年二手手機(jī)買賣與市場推廣合作協(xié)議3篇
- 滿洲里俄語職業(yè)學(xué)院《云計算原理及應(yīng)用》2023-2024學(xué)年第一學(xué)期期末試卷
- 影視動畫資源庫相關(guān)專業(yè)介紹
- 【教學(xué)創(chuàng)新大賽】《數(shù)字電子技術(shù)》教學(xué)創(chuàng)新成果報告
- 咖啡因提取的綜合性實驗教學(xué)
- GONE理論視角下宜華生活財務(wù)舞弊案例分析
- 初中語文默寫競賽方案
- 2023電力建設(shè)工程監(jiān)理月報范本
- 汽車空調(diào)檢測與維修-說課課件
- 氨水濃度密度對照表
- 白雪歌送武判官歸京公開課一等獎?wù)n件省課獲獎?wù)n件
- 園林植物栽培與環(huán)境
- 小型雙級液壓舉升器設(shè)計
- 9月支部委員會會議記錄
評論
0/150
提交評論