GoF说明:
定义一组算法并封装每个算法,让他们可以彼此互相使用。策略模式能让客户端在使用它们时更加独立。
模式说明:
当我们需要计算一样东西、但是计算过程会依赖外界的变化而变化时,我们就使用策略模式对算法进行封装。定义一个接收者,接收者持有一个算法供客户端对象调用,当外界发生改变时,我们改变接收者的算法。但是客户端调用的接口保持不变,这样开发的时候我们就能专注与不同算法的开发而不是调用流程的开发。
三个重要对象:
ConcreteStrategy:具体算法
Strategy:持有一个算法,并提供接口为客户端对象计算接口
Context:持有一个Sctragy对象计算结果
流程图分析:
案例分析:角色属性计算
1.需求说明:通常游戏中只有一个角色基类,但是不同阵营的角色同一种属性的计算方式可能有所不同。
2.代码分析:
属性基类:
public abstract class ICharaterAttr{
protected int mHp;
protected int mAttack;
public IAttrStragy mAttrStragy;
//提供只读属性对外开放
public int hp { get { return mAttrStragy.getHp(); } }
public int attack { get { return mAttrStragy.getAttack(); } }
public ICharaterAttr(IAttrStragy stragy,int hp,int attack){
mHp = hp;
mAttack = attack;
setStrragy(stragy);
}
public void setStrragy(IAttrStragy stragy){
mAttrStragy = stragy;
mAttrStragy.init(this);
}
}
属性计算策略基类:
public abstract class IAttrStragy {
protected ICharaterAttr mAttr;
public void init(ICharaterAttr attr){
mAttr = attr;
}
public abstract int getHp();
public abstract int getAttack();
}
实现两种角色的角色策略:
public class Npc_1_AttrStragy : IAttrStragy {
public override int getHp(){
return this.mAttr.hp * 100;
}
public override int getAttack(){
return this.mAttr.mAttack* 10;
}
}
public class Npc_2_AttrStragy : IAttrStragy {
public override int getHp(){
return this.mAttr.hp * 10;
}
public override int getAttack(){
return this.mAttr.mAttack* 2;
}
}
角色拥有一个ICharaterAttr对象,使用代码如下:
public abstract class ICharacter{
protected ICharaterAttr mAttr;
public ICharacter(IAttrStragy stragy){
mAttr = new ICharaterAttr(stragy,1,2);
}
public void setStragy(IAttrStragy stragy){
mAttr.setStrragy(stragy,4,5);
}
//当需要取人物的血量时
public int getHp(){
return mAttr.hp;
}
//当需要人物的攻击时
public int getAttack(){
return mAttr.attack;
}
//当然以上两项我们也可以做成只读属性
}
这样下来,就把基础属性在不同的npc变化的计算过程独立开,让我们更加专注与开发不同的npc属性,而不是将属性的开发带入到整个角色的开发维护中。并且角色策略的修改十分方便,