概述:
本文介紹一種“邏輯持久化技術”。目的是進一步提升代碼復用程度。主要應用場景在游戲中,例如人物角色升級、事物隊列冷卻等。
前言:
開發游戲中,經常看到一些業務邏輯相似,但是又無法復用的代碼。例如升級。
英雄:每100點經驗升級1級。
騎寵:每100點經驗升級1星,每12星升級一級。
如果用傳統的設計思路,會得到以下代碼片段:
USR_HERO { public int exp; public int level; } UsrHeroDao { public boolean upgrade( USR_HERO hero, int exp) { hero.exp += exp; if (hero.exp >= MAX_EXP) { hero.exp = MAX_EXP - hero.exp; hero.level += 1; } } }
如果是寵物,就寫一套寵物的升級代碼。這種代碼開發多了,就開始覺得煩,但是不認真看又會出Bug。我們程序員尼瑪怎么能每天都重復的干著這些無聊的事情??
于是我開始冥思苦想,如果這些能力是模塊,一個對象安裝了這個模塊,就具備了升級的能力,那我就不用開發了啊。多爽??不斷的冥思苦想,曾經還半夜在家里的大廳摸黑轉來轉去,大腦不斷構造著各種架構,又不斷的被推翻。
終于,有一天, 我走在回家的路上的時候,給我想到了!!!
(PS: 各位看解決方案的時候,也可以稍微1分鐘思考下上面的問題)
核心思路:
首先要分析為什么代碼不能復用。因為升級的經驗值是值類型對象!這個就是一切的根源本質。可以想象下,如果把對象的經驗、等級放入方法內運算,實際上對象的值是沒有受到影響的,因為按值傳遞被拷貝了一份。
所以???把值類型轉成對象類型,突然間一切都柳暗花明了。例如:
OrmInt { public int value; } USR_HERO { public OrmInt exp; public OrmInt level; }
看到這里,大家是否突然間明白了?突然間覺得高端大氣上檔次了?尼瑪這可是我奮戰幾天的結果。我相信我不說,業界起碼3年內不會有人往這個方向思考(臭美一下,各位大俠手下留情,千萬別噴我。。。。。)
現在我把升級的方法修改一下:
UsrHeroDao { public boolean upgrade(OrmInt exp, OrmInt level, int exp) { exp.value += exp; If(exp.value >= MAX_EXP) { exp.value = MAX_EXP - exp; level.value += 1; } } }
怎樣?是不是覺得爽了很多。
案例:
為了進一步說明這個“邏輯持久化”如何的高端,我舉個我實際使用的例子, 使用了簡化代碼:
// 為OrmInt增加一個可升級的方法,返回升級對象。 OrmInt { public OrmUpgradable ugprade(OrmInt upgradeValue, OrmUpgradeLimit upgradeLimited) { OrmUpgradable value = new OrmUpgradable(this, value, ugpradeLimited); } } // 升級對象,支持鏈式編程,實現升級觸發下一升級的效果 OrmUpgradable { private OrmInt value; // 被升級的對象 private OrmInt upgradeValue; // 當前升級的值 private OrmUpgradeLimit upgradeLImited; // 升級的上限對象 private OrmUpgradable head; // 鏈式升級的頭 private OrmUpgrade child; // 鏈式升級的尾 // 觸發下一個升級 public OrmUpgradable upgrade(OrmInt value, OrmInt upgradeValue, OrmUpgradeLimit upgradeLimited) { OrmUpgradable orm = new OrmUpgradable(value, upgradeValue, upgradeLimited); orm.head = this.head; this.child = orm; return orm; } // 開始升級 public boolean doWhile() { // 不斷循環升級 if(this.value.greatThan(0)) { // 當前的升級上限 int upgradeLimited = this.upgradeLimited.getUpgradeLimit(); // 計算可升級的值的部分 并升級 int incValue = min(upgradeLimited.substract(this.value), upgradeValue); this.value.increase(incValue); //判斷是否升級 if(this.value.greatEqualThan(upgradeLimit)) { // 鏈式觸發后續的升級 if(!this.child.doWhile()) return true; } // 更新剩余可升級部分 upgradeValue.update(upgradeValue.substract(incValue)); this.value.update(0); } return true; } }
使用方法:
p.value.upgrade(11, 10)
.upgrade(p.value2, 1, 10)
.upgrade(p.value3, 1, 10)
.doWhile()
這段代碼用起來簡單,但是原理有點復雜。
- 首先這是個鏈式升級。當exp值增加到達了最大值,則觸發下個對象level進行增加,一直觸發到最后。然后一個循環。
- 其次,exp不斷升級,直到可升級的值用完了。感覺就像一個儲水池。
- 最后,升級上限我用了一個對象OrmUpgradeLimit,原因是實際項目中,當用戶的等級不同的時候,當前等級經驗值上限是不一樣的。所以OrmUpgradeLimit實際上內部包含了level這個對象。而由于level是類型對象,因此在升級過程中,升級上限是動態變化的。
小結:
本文拋磚引玉,介紹了一種非常強大的“業務邏輯持久化”技術。本質就是值類型轉對象類型;對象類型除了包含數據外,并帶上處理方法。
這樣,這個對象復制給了Orm,Orm就具備了對應的能力。所以我命名為“業務邏輯持久化”,因為我把邏輯放在了持久層。
擴展閱讀:
實際上現在的業務邏輯操作,都是圍繞著數據。
邏輯更確切的說,就是圍繞相互有關聯的數據字段進行邏輯操作。 思維發散下,就明白。這個已經不是對某個對象進行操作了。
英雄有經驗等級、坐騎也有經驗等級,但是升級這個操作實際上是針對經驗和等級這2個數據建立關系,而不是英雄和坐騎。
這個技術國外叫做:functional reactive programming
Hudak, Paul (September 1989). "Conception, evolution, and application of functional programming languages" (PDF). ACM Computing Surveys 21 (3): 359–411. doi:10.1145/72551.72554.
下期預告:
領先業界3年的游戲開發技術——頂級數據庫持久層的設計。
目前最流行的數據庫持久層是什么?Hibernate?ADO.NET?不,Hibernate從出生開始,我就覺得他實在太落后了。歡迎關注6月份的主題——頂級數據庫持久層設計。
關于我們:
我們來自Pixysoft獨立游戲制作人。我們的目標是培養早就游戲行業的獨立制作人,提供一切相關的技術文檔資料,從前端到后端、策劃、數值、美術全方位進行培養。
歡迎加入我們的群:95755843
本群每月1日~10日為開放日,不限條件加入。11~30日為閉關日,除了成員邀請外,不對外開放,進行封閉培訓。
本群關注的是思想的交流,其次借助開源平臺共享資源。
歡迎游戲愛好者加入。
文章列表