王者荣耀与Java策略模式

一.什么是策略模式

(1)策略模式属于对象的行为模式。其用意是针对一组算法,将每一  
个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替  
换。策略模式使得算法可以在不影响到客户端的情况下发生变化。

(2)策略模式是对算法的包装,是把使用算法的责任和算法本身分  
割开来,委派给不同的对象管理。策略模式通常把一个系列的算法  
包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句  
话来说,就是:“准备一组算法,并将每一个算法封装起来,使得  
它们可以互换”。

二.策略模式的结构

(1)这个模式涉及到三个角色:
    环境(Context)角色:持有一个Strategy的引用。
    抽象策略(Strategy)角色:这是一个抽象角色,通常由一个  
接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
    具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。

(2)策略模式的重心
  策略模式的重心不是如何实现算法,而是如何组织、调用这些算  
法,从而让程序结构更灵活,具有更好的维护性和扩展性。

(3)算法的平等性
  策略模式一个很大的特点就是各个策略算法的平等性。对于一  
系列具体的策略算法,大家的地位是完全一样的,正因为这个平等  
性,才能实现算法之间可以相互替换。所有的策略算法在实现上也是相互独立的,相互之间是没有依赖的。
  所以可以这样描述这一系列策略算法:策略算法是相同行为的不同实现。

(4)运行时策略的唯一性
  运行期间,策略模式在每一个时刻只能使用一个具体的策略实现  
对象,虽然可以动态地在不同的策略实现中切换,但是同时只能使用一个。

(5)公有的行为
  经常见到的是,所有的具体策略类都有一些公有的行为。这时候  
,就应当把这些公有的行为放到共同的抽象策略角色Strategy类里面。  
当然这时候抽象策略角色必须要用Java抽象类实现,而不能使用接口。
  这其实也是典型的将代码向继承等级结构的上方集中的标准做法。

三.以王者荣耀为例说明

UML类图.JPG

王者荣耀里面召唤师技能(Summoner Spells)有:


召唤师技能.png
惩戒:对身边的野怪和小兵造成真实伤害并眩晕1秒(30秒的CD,1级解锁) 
斩杀:立即对身边敌军英雄造成其已损失生命值14%的真实伤害(90秒CD,3级解锁)  
狂暴:增加攻击速度60%,并增加物理攻击力10%持续5秒(60秒CD,5级解锁)
疾跑:增加30%移动速度持续10秒(100秒CD,7级解锁)
治疗术:回复自己与附近队友15%生命值,提高附近友军移动速度15%持续2秒(120秒CD,9级解锁)
干扰:沉默机关持续5秒(60秒CD,11级解锁)
眩晕:晕眩身边所有敌人0.75秒,并附带持续1秒的减速效果(90秒CD,13级解锁)
净化:解除自身所有负面和控制效果并免疫控制持续1.5秒(120秒CD,15级解锁)
弱化:减少身边敌人伤害输出30%持续2.5秒(90秒CD,17级解锁)
闪现:向指定方向位移一段距离(120秒CD,19级解锁)

将里面的召唤师技能抽象出来有(攻击方式,效果持续时间,冷却  
时间,解锁等级等规则),而这些规则算法封装起来使得它们可以  
互换。

建立一个抽象策略(Strategy)角色类SummonerSpells:
public interface  SummonerSpells{
     public void use(Self self,Enermy enermy){
          //do something  
    }
}
实体类:
package com.lrq.test;

public class Enermy {
    private int cd;
    private  int level;
    private  boolean lock;
    private  double  currentHp;
    private  double  fullHp;
    private  double attack;
    private  String controlEffect;
    private  String  shift;
    private  double moveSpeed;
    
    public Enermy() {
        super();
    }
    public int getCd() {
        return cd;
    }
    public void setCd(int cd) {
        this.cd = cd;
    }
    public int getLevel() {
        return level;
    }
    public void setLevel(int level) {
        this.level = level;
    }
    public boolean isLock() {
        return lock;
    }
    public void setLock(boolean lock) {
        this.lock = lock;
    }
    public double getCurrentHp() {
        return currentHp;
    }
    public void setCurrentHp(double currentHp) {
        this.currentHp = currentHp;
    }
    public double getFullHp() {
        return fullHp;
    }
    public void setFullHp(double fullHp) {
        this.fullHp = fullHp;
    }
    public double getAttack() {
        return attack;
    }
    public void setAttack(double attack) {
        this.attack = attack;
    }
    public String getControlEffect() {
        return controlEffect;
    }
    public void setControlEffect(String controlEffect) {
        this.controlEffect = controlEffect;
    }
    public String getShift() {
        return shift;
    }
    public void setShift(String shift) {
        this.shift = shift;
    }
    public double getMoveSpeed() {
        return moveSpeed;
    }
    public void setMoveSpeed(double moveSpeed) {
        this.moveSpeed = moveSpeed;
    }
    @Override
    public String toString() {
        return "Enermy [cd=" + cd + ", level=" + level + ", lock=" + lock
                + ", currentHp=" + currentHp + ", fullHp=" + fullHp
                + ", attack=" + attack + ", controlEffect=" + controlEffect
                + ", shift=" + shift + ", moveSpeed=" + moveSpeed + "]";
    }
    
    
}
--------------------------------------------------------------------------
package com.lrq.test;

public class  Self {
    private int cd;
    private  int level;
    private  boolean lock;
    private  double  currentHp;
    private  double  fullHp;
    private  double attack;
    private  String controlEffect;
    private  String  shift;
    private  double moveSpeed;
    public Self() {
        super();
    }
    public int getCd() {
        return cd;
    }
    public void setCd(int cd) {
        this.cd = cd;
    }
    public int getLevel() {
        return level;
    }
    public void setLevel(int level) {
        this.level = level;
    }
    public boolean isLock() {
        return lock;
    }
    public void setLock(boolean lock) {
        this.lock = lock;
    }
    public double getCurrentHp() {
        return currentHp;
    }
    public void setCurrentHp(double currentHp) {
        this.currentHp = currentHp;
    }
    public double getFullHp() {
        return fullHp;
    }
    public void setFullHp(double fullHp) {
        this.fullHp = fullHp;
    }
    public double getAttack() {
        return attack;
    }
    public void setAttack(double attack) {
        this.attack = attack;
    }
    public String getControlEffect() {
        return controlEffect;
    }
    public void setControlEffect(String controlEffect) {
        this.controlEffect = controlEffect;
    }
    public String getShift() {
        return shift;
    }
    public void setShift(String shift) {
        this.shift = shift;
    }
    public double getMoveSpeed() {
        return moveSpeed;
    }
    public void setMoveSpeed(double moveSpeed) {
        this.moveSpeed = moveSpeed;
    }
    @Override
    public String toString() {
        return "Self [cd=" + cd + ", level=" + level + ", lock=" + lock
                + ", currentHp=" + currentHp + ", fullHp=" + fullHp
                + ", attack=" + attack + ", controlEffect=" + controlEffect
                + ", shift=" + shift + ", moveSpeed=" + moveSpeed + "]";
    }
    
}
---------------------------------------------------------------------------------
然后建立几个具体策略(Strategy)角色类:
1.惩戒Discipline(打野专用)
public interface  Discipline{
     public void use(Self self,Enermy enermy){
            enermy.currentHp - = 850;
            enermy.controlEffect = "眩晕1秒";
    }
}

2.斩杀(前排专用)
public interface  Beheaded{
     public void use(Self self,Enermy enermy){
             enermy.currentHp-= (enermy.fullHp-enermy.currentHp)*14%;
         
    }
}

3.闪现(adc)

public interface  Flash{
     public void use(Self self,Enermy enermy){
          self.shif+=100;       
          self.controlEffect="向前闪现一小段";
    }
}


4.治疗(adc或者辅助)
public interface  Treatment{
     public void use(Self self,Enermy enermy){
          self.currentHp+=self.fullHp*15%; 
          self.moveSpeed+= self.moveSpeed*15%;
          self.controlEffect="回复自己与附近队友15%生命值,提高附近友军移动速度15%持续2秒";
    }
}
--------------------------------------------------------------------------------------------------------
然后环境(Context)角色:Summoner----召唤师

public class Summoner{
    //持有一个具体的策略对象
    private  SummonerSpells  summonerSpells;//召唤师技能
    /**
     * 构造函数,传入一个具体的策略对象
     * @param strategy    具体的策略对象
     */
    public Summoner(SummonerSpells  summonerSpells){
        this.summonerSpells= summonerSpells;
    }
    
    /**
     * 计算生命值,控制效果,移速等
     * @param Enermy,Self    敌人,自己
     * @return    
     */
    public void quote(Self self,Enermy enermy){
        return summonerSpells.use(Self self,Enermy enermy);
    }
}
--------------------------------------------------------------------------------------------------------
最后客户端Client :
public class Client {

    public static void main(String[] args) {
        //选择并创建需要使用的策略对象
        Flash flash= new flash(new Self(),new Enermy());
        //创建环境
        Summoner summoner= new Summoner(flash);
        //计算属性
        flash.use();
    }

}

四.策略模式的优缺点

1. 策略模式的优点:

  (1)策略模式提供了管理相关的算法族的办法。策略类的等级结构  
定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里  
面,从而避免代码重复。

  (2)使用策略模式可以避免使用多重条件(if-else)语句。多重条件  
语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或  
行为的逻辑混合在一起,统统列在一个多重条件语句里面,比使用继承  
的办法还要原始和落后。

2.策略模式的缺点:

  (1)客户端必须知道所有的策略类,并自行决定使用哪一个策略  
类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当  
的算法类。换言之,策略模式只适用于客户端知道算法或行为的情况。

  (2)由于策略模式把每个具体的策略实现都单独封装成为类,  
如果备选的策略很多的话,那么对象的数目就会很可观。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容