设计模式—策略模式(用lol来分析)

转载注明出处:https://blog.csdn.net/qq_39071530/article/details/84172844

github地址 https://github.com/esmusssein777/designpatterns

所有设计模式目录 https://blog.csdn.net/qq_39071530/article/details/84849070

 

首先关心的是什么时候要用到策略模式!

我们来关心下面的例子。

 

英雄联盟的英雄有四个基础技能和两个召唤师技能。

每个英雄的基础技能都不相同(对应的是Q、W、E、R),

但是召唤师技能却是在多个里面选择的,可以相同(对应D、F)。

 

我们先来考虑一种情况。

我们将超类设计成

设计模式—策略模式(用lol来分析)_第1张图片

我们会发现有以下的缺点:

1、代码在多个子类中重复(实现召唤师技能的D和F的代码重复)

2、运行时行为不容易改变(我们在选择召唤师技能DF时需要重新的覆盖D、F)

3、很难知道召唤师技能的全部行为(假如版本改变,召唤师技能DF也改变)

4、改变会牵一发动全身,如果某个召唤师技能覆盖错误会导致bug。

 

于是我们定义一个接口,至于有什么好处可以看我的EffectiveJava学习笔记系列。

以下的就是定义了行为类。

定义一个召唤师技能的行为。里面有传送、闪现、治疗等等。

设计模式—策略模式(用lol来分析)_第2张图片

我们来看一下完整的类uml图

我们创建了EZ和VN两个英雄来继承超类。

在里面分别的实现自己的qwer技能。

并选择召唤师技能的行为作为自己的 d、f 技能。

设计模式—策略模式(用lol来分析)_第3张图片

下面是代码

Hero.java

package org.ligz.DesignPatterns.Strategy.hero;

public abstract class Hero {
	DFBehavior dBehavior;//使用D技能
	DFBehavior fBehavior;//使用F技能
	
	public Hero() {
		System.out.println("创建英雄");
	}
	
	public void DSkill() {
		dBehavior.skill();
	}
	
	public void FSkill() {
		fBehavior.skill();
	}
	
	public void fight() {
		System.out.println("打架");
	}
	
	/**
	 * 基础技能
	 */
	public abstract void Q();
	
	public abstract void W();
	
	public abstract void E();
	
	public abstract void R();
}

 DFBehavior.java

package org.ligz.DesignPatterns.Strategy.hero;

public interface DFBehavior {
	public void skill();
}

Falsh.java 

package org.ligz.DesignPatterns.Strategy.hero;

public class Falsh implements DFBehavior{

	public void skill() {
		System.out.println("使用闪现");		
	}
	
}

Cure.java 

package org.ligz.DesignPatterns.Strategy.hero;

public class Cure implements DFBehavior{

	public void skill() {
		System.out.println("使用治疗");
	}

}

TP.java 

package org.ligz.DesignPatterns.Strategy.hero;

public class TP implements DFBehavior{

	public void skill() {
		System.out.println("使用传送");		
	}
}

 EZ.java

package org.ligz.DesignPatterns.Strategy.hero;

public class EZ extends Hero{
	
	public EZ() {
		super();
		System.out.println("是时候展示真正的技术了");
		dBehavior = new Falsh();
		fBehavior = new TP();
	}

	@Override
	public void Q() {
		System.out.println("EZ的q技能");
	}

	@Override
	public void W() {
		System.out.println("EZ的w技能");
	}

	@Override
	public void E() {
		System.out.println("EZ的e技能");		
	}

	@Override
	public void R() {
		System.out.println("EZ的r技能");		
	}

}

VN.java 

package org.ligz.DesignPatterns.Strategy.hero;

public class VN extends Hero{
	public VN() {
		super();
		System.out.println("让我们来猎杀那些陷入黑暗中的敌人");
		dBehavior = new Falsh();
		fBehavior = new Cure();
	}

	@Override
	public void Q() {
		System.out.println("VN的q技能");
	}

	@Override
	public void W() {
		System.out.println("VN的w技能");
	}

	@Override
	public void E() {
		System.out.println("VN的e技能");
	}

	@Override
	public void R() {
		System.out.println("VN的r技能");
	}

}

下面是测试的代码 

package org.ligz.DesignPatterns.Strategy.hero;

public class Test {
	public static void main(String[] args) {
		Hero ez = new EZ(); 
		ez.fight();
		ez.DSkill();
		ez.FSkill();
		
		System.out.println("+++++++++++++++");
		
		Hero vn = new VN();
		vn.fight();
		vn.DSkill();
		vn.FSkill();
	}
}
创建英雄
是时候展示真正的技术了
打架
使用闪现
使用传送
+++++++++++++++
创建英雄
让我们来猎杀那些陷入黑暗中的敌人
打架
使用闪现
使用治疗

 

我们脱离例子来分析代码,会发现  “有一个”  可能比  ”是一个”  更好。 

英雄Hero类有一个行为是DF召唤师技能。

每一个英雄都有一个DFBehavior行为,好处是将召唤师技能委托给他代为处理,这里可能是有多个行为。比如说符文也可以是一个Behavior行为。我们同样用这种方式扩展。

这就是组合。

这种做法和继承不同的地方在于,英雄的行为不是继承来的,而是适当的行为对象组合来的。

这样做有很大的弹性。

 

回到定义:

策略模式定义了算法族(召唤师技能,或者说是符文),分别封装起来,让他们之间可以相互替换,此模式可以让算法的变化独立于使用算法的客户(英雄)。

 

你可能感兴趣的:(设计模式,设计模式学习笔记)