开始的话
最近都在忙课程设计和考试,但是计划是学习人工智能和重构,难得挤出时间看这本好书--<重构,改善既有代码的设计>.看了之后受益匪浅,因为
终于知道了为什么觉得自己的代码和高手写的代码还是有一大截差距,现在终于知道,好的代码不是一开始就写得十分好的,好的代码是通过优化和重构
一点一点地推敲出来的,可能现在写的代码还是很烂,但是有一颗重构的心,一定能缩小和编程高手的差距
最近都在忙课程设计和考试,但是计划是学习人工智能和重构,难得挤出时间看这本好书--<重构,改善既有代码的设计>.看了之后受益匪浅,因为
终于知道了为什么觉得自己的代码和高手写的代码还是有一大截差距,现在终于知道,好的代码不是一开始就写得十分好的,好的代码是通过优化和重构
一点一点地推敲出来的,可能现在写的代码还是很烂,但是有一颗重构的心,一定能缩小和编程高手的差距
开始
马上进入正题,这本书我也是只看了60来页,就迫不及待地重构自己的代码了,因为书中描述的情况十分符合我手头上的练手项目,特别是
大量的switch和if这种条件表达式怎么用技巧来改善,这样整个代码的结构就清晰了,而且扩展性随之也提高了,一开始我选择的模块是我的
技能释放类,优化之前的代码是这样的,不好意思,我忘记保存重构之前的代码了,但是大概结构是这样的
马上进入正题,这本书我也是只看了60来页,就迫不及待地重构自己的代码了,因为书中描述的情况十分符合我手头上的练手项目,特别是
大量的switch和if这种条件表达式怎么用技巧来改善,这样整个代码的结构就清晰了,而且扩展性随之也提高了,一开始我选择的模块是我的
技能释放类,优化之前的代码是这样的,不好意思,我忘记保存重构之前的代码了,但是大概结构是这样的
public void PlayerAttack(PlayerSkillType type){
switch (type)
{
case(PlayerSkillType.NORMALSKILL):
//处理普通技能释放逻辑
break;
case (PlayerSkillType.FIRSTSKILL):
//处理第一个技能释放的逻辑
break;
case (PlayerSkillType.THIRDSKILL):
//处理第三个技能释放的逻辑
break;
}
}
这种结构现在来说还比较易读,但是当我想增加几个技能的时候发现,很多东西都要重写一次,十分麻烦,那么怎么重构呢???
这是书上介绍的方法概括:
运用多态取代价格相关的条件逻辑
使用条件: 手上有个条件表达式,它根据对象类型的不同而选择不同的行为
用法: 将这个条件表达式的每个分支放进一个子类内的复写函数中,然后将原始函数声明为抽象函数
1. 把条件表达式提炼到一个独立的函数中
2. 可以把条件表达式函数放置在继承结构的顶端
3. 在子类建立一个函数, 让它复写父类中条件表达式函数, 将与该子类相关的条件表达式分支复制在在新建函数中
4. 在父类中删除条件表达式函数内被复制了的分支
使用条件: 手上有个条件表达式,它根据对象类型的不同而选择不同的行为
用法: 将这个条件表达式的每个分支放进一个子类内的复写函数中,然后将原始函数声明为抽象函数
1. 把条件表达式提炼到一个独立的函数中
2. 可以把条件表达式函数放置在继承结构的顶端
3. 在子类建立一个函数, 让它复写父类中条件表达式函数, 将与该子类相关的条件表达式分支复制在在新建函数中
4. 在父类中删除条件表达式函数内被复制了的分支
理论总是让人糊涂,直接上代码吧
1.把条件表达式提炼到一个独立的函数中:上面的代码已经把这件事情给做了
2. 可以把条件表达式函数放置在继承结构的顶端
那现在我们新建一个类,叫做PlayerSkillType,作为抽象类,
2. 可以把条件表达式函数放置在继承结构的顶端
那现在我们新建一个类,叫做PlayerSkillType,作为抽象类,
public abstract class PlayerSkillType
{
public const int NORMALSKILL = 3;
public const int FIRSTSKILL = 0;
public const int SECONDSKILL = 1;
public const int THIRDSKILL = 2;
private PlayerSkillType _type;
private int getType()
{
return _type.getTypeCode();
}
public abstract int getTypeCode();
public abstract void PlayerSkillAttack();
}
3.在子类建立一个函数, 让它复写父类中条件表达式函数, 将与该子类相关的条件表达式分支复制在在新建函数中
新建三个子类,分别是FirstSkillType,NormalSkillType,ThirdSkillType这三个继承PlayerSkillType并实现抽象方法,覆写父类中的
条件表达式
新建三个子类,分别是FirstSkillType,NormalSkillType,ThirdSkillType这三个继承PlayerSkillType并实现抽象方法,覆写父类中的
条件表达式
public class FirstSkillType : PlayerSkillType {
public override int getTypeCode()
{
return PlayerSkillType.FIRSTSKILL;
}
public override void PlayerSkillAttack()
{
int skill1AttValue = (int)(playerStatus.getPhyAtt() * 1.5);
EnemyManager.getInstance().EnemyTakeDamaged(skill1AttValue);
EnemyManager.getInstance().Skill1EnemyEffect();
}
}
public class NormalSkillType : PlayerSkillType
{
public override int getTypeCode()
{
return PlayerSkillType.NORMALSKILL;
}
public override void PlayerSkillAttack()
{
Debug.Log("skill1");
int phyAttValue = playerStatus.getPhyAtt();
EnemyManager.getInstance().EnemyTakeDamaged(phyAttValue);
}
}
public class ThirdSkillType : PlayerSkillType {
public override int getTypeCode()
{
return PlayerSkillType.NORMALSKILL;
}
public override void PlayerSkillAttack()
{
Debug.Log("群体攻击");
var skill3AttValue = (int)(playerStatus.getPhyAtt() * 4.5);
EnemyManager.getInstance().AllEnemyTakeDamaged(skill3AttValue);
}
}
最后再在调用它的类中改一下代码
public class playerAttack : MonoBehaviour {
//持有PlayerSkillType的一份引用
private PlayerSkillType _type;
private NormalSkillType normalType = new NormalSkillType();
private FirstSkillType firstSkillType = new FirstSkillType();
private ThirdSkillType thirdSkillType = new ThirdSkillType();
public void PlayerAttack(int typeCode)
{
this.setCurrentSkillType(typeCode);
this._type.PlayerSkillAttack();
//MP减少
if (_type.getTypeCode() == (PlayerSkillType.NORMALSKILL))
{
//普通攻击不使用MP
return;
}
else
{
}
}
public void setCurrentSkillType(int typeCode)
{
switch (typeCode)
{
case(PlayerSkillType.NORMALSKILL):
this._type = this.normalType;
break;
case (PlayerSkillType.FIRSTSKILL):
this._type = this.firstSkillType;
break;
case (PlayerSkillType.THIRDSKILL):
this._type = this.thirdSkillType;
break;
}
}
}
当然,这还没完全重构完,因为还有很多可以重构的地方,比如各个技能释放时伤害的计算方式和释放技能后扣减MP的函数.功能也是十分简单,知道面向对象的多态的话大概都能看懂.但是终于让我知道,要修炼成编程高手必须要懂得重构,这样阅读商业游戏源码的时候就能跟上它的思路了.而且在重构的时候一定要进行单元测试,以确保现在的重构是有条不紊地进行,这个过程不能急,一点一点把自己的代码优化起来.这篇写得比较仓促,因为还有课程设计要做,就先到这里了