網(wǎng)站的建設(shè)創(chuàng)新互聯(lián)公司專注網(wǎng)站定制,經(jīng)驗豐富,不做模板,主營網(wǎng)站定制開發(fā).小程序定制開發(fā),H5頁面制作!給你煥然一新的設(shè)計體驗!已為成都混凝土泵車等企業(yè)提供專業(yè)服務(wù)。
妹子開始抱怨起來
妹子的游戲是個對戰(zhàn)類的游戲,其中有一個玩家的概念,玩家可以***,這個業(yè)務(wù)正是妹子開始撓頭的起點
產(chǎn)品經(jīng)理:玩家有很多屬性,例如:身高,性別 blalalala ,玩家可以***其他玩家。
YY妹子寫程序也是很利索,一天就把程序搞定了,而且還抽象出一個palyer的基類出來,堪稱高級程序員必備技能。
//玩家的基礎(chǔ)抽象類
abstract class Player
{
public string Name { get; set; }
//.
//.
//.
//玩家的***
public abstract void Attack();
}
//真實玩家
class PersonPlayer : Player
{
public override void Attack()
{
//to do something
return;
}
}
產(chǎn)品經(jīng)理:游戲里我需要增加機器人玩家來增加游戲在線的人數(shù),機器人屬性和真實玩家一樣,但是***不太一樣
這個需求修改還是難不住YY妹子,沒過幾天代碼改好了,增加了一個機器人玩家的類,用到了OO的繼承。在這里為玩家抽象類點贊
class RobotPlayer : Player
{
public override void Attack()
{
//修改***內(nèi)容等 to do something
return;
}
}
產(chǎn)品經(jīng)理:我要創(chuàng)建一批類似玩家的怪物,沒有真實玩家的那些屬性,但是和真實玩家一樣有***行為
這個時候YY妹子終于意識到***是一種行為了,需要抽象出接口來了。
//***接口
interface IAttack
{
void Attack();
}
//玩家的基礎(chǔ)抽象類
abstract class Player
{
//其他屬性代碼省略一萬字
}
//真實玩家
class PersonPlayer :Player, IAttack
{
public void Attack()
{
//to do something
return;
}
}
//機器人玩家
class RobotPlayer :Player, IAttack
{
public void Attack()
{
// to do something
return;
}
}
//怪物玩家
class MonsterPlayer : IAttack
{
public void Attack()
{
// to do something
return;
}
}
到了這里,我們遇到了大家耳熟能詳?shù)拿嫦蚪涌诰幊?,沒錯,這個做法是對的。這也是設(shè)計的一大原則:程序依賴接口,不依賴具體實現(xiàn)。這里要為YY繼續(xù)點贊。順便說一下,在多數(shù)情況下,很多同學(xué)就到此為止了
產(chǎn)品經(jīng)理:我現(xiàn)在要設(shè)計玩家的***方式了,目前有遠程***,近程***,貼身***這三類,其他需求 blalalalala。
據(jù)說此刻YY妹子的心里是一萬頭羊駝飄過的狀態(tài)。這次要怎么設(shè)計呢?這也是菜菜要說的重點部分。
現(xiàn)在我們需要靜下心來思考一番了,為什么我們使用了面向接口編程,遇到這次需求,程序還是需要修改很多東西呢?
設(shè)計原則:找出應(yīng)用中將來可能變化的地方,把他們獨立出來,不需要和那些不變的代碼混在一起。
這樣的概念很簡單,確是每個設(shè)計模式背后的靈魂所在。到目前為止,設(shè)計中不斷在變的是Attack這個接口,更準(zhǔn)確的應(yīng)該是Attack這個行為。面向接口這個概念沒有問題,是大多數(shù)人把語言層面和設(shè)計層面的接口含義沒搞明白,真正的面向接口編程更偏向于面向架構(gòu)中行為的編程,另外一個角度也可以看做是利用OO的多態(tài)原則。
說到這里,我們可以更系統(tǒng)的給Attack行為定義成一類行為,而具體的行為實現(xiàn)可以描述為一簇算法。想想看,Attack行為其實不止作用于player的類型,改日產(chǎn)品經(jīng)理新加一個XX對象也具有***行為,理想的情況是我只需要讓這個xx對象有Attack行為即可,而不需要改動以前的任何代碼。你現(xiàn)在是不是對這個行為的定義理解的更深刻一些。
兩外一點,到目前為止YY妹子的代碼中一直是以繼承的方式來實現(xiàn)行為,這會有什么問題呢?假如要想在程序運行時動態(tài)修改player的Attack行為,會顯得力不從心了。
談到這里又引入了其他一個設(shè)計理念:一般情況下,有一個可能比是一個更好。具體概念為:多用組合,少用繼承。繼承通常情況下適用于事物本身的一些特性,比如:玩家基類具有姓名這個屬性,繼承類完全可以繼承這個屬性,不會發(fā)生任何問題。而組合多用于行為的設(shè)計方面,因為這個行為類型,我可能會在多個事物中出現(xiàn),用組合能實現(xiàn)更大的彈性設(shè)計。
//***行為接口
interface IAttack
{
void Attack();
}
class RemoteAttack : IAttack
{
public void Attack()
{
//遠程***
}
}
class ShortAttack : IAttack
{
public void Attack()
{
//近程***
}
}
//玩家的基礎(chǔ)抽象類
abstract class Player
{
//其他屬性代碼省略一萬字
}
//真實玩家
class PersonPlayer : Player
{
//玩家可以有***的行為
IAttack attack;
public PersonPlayer(IAttack _attack)
{
attack = _attack;
}
public void Attack()
{
//調(diào)用行為一簇算法的實現(xiàn)
attack.Attack();
return;
}
//玩家可以運行時修改***行為
public void ChangeAttack(IAttack _attack)
{
attack = _attack;
}
}
接口是一種規(guī)范和約束,更高層的抽象更像是一類行為,面向接口編程只是代碼層體現(xiàn)的一種格式體現(xiàn)而已,真正的面向接口設(shè)計更貼近面向行為編程
添加關(guān)注,查看更精美版本,收獲更多精彩