定义
定义一组算法,将每个算法都封装起来,并使他们之间可以互换。
策略模式是对算法的封装,把一系列算法分别封装到对应的类中,并且这些类实现相同的接口,这些类之间可以互相替换。
StrategyContext
- 这里体现了Java的多态
package com.zhangyu.myapplication.strategy;
public class StrategyContext {
private StrategyAbstract strategyAbstract;
public void setStrategyAbstract(StrategyAbstract strategyAbstract) {
this.strategyAbstract = strategyAbstract;
}
public float price(int km){
return strategyAbstract.calculatePrice(km);
}
}
StrategyAbstract
package com.zhangyu.myapplication.strategy;
public interface StrategyAbstract {
float calculatePrice(int km);
}
Strategy1
package com.zhangyu.myapplication.strategy;
public class StrategyBus implements StrategyAbstract {
@Override
public float calculatePrice(int km) {
return km * 1;
}
}
Strategy2
package com.zhangyu.myapplication.strategy;
public class StrategySubway implements StrategyAbstract {
@Override
public float calculatePrice(int km) {
return km * 2;
}
}
调用
float price;
int km = 20;
StrategyContext strategyContext = new StrategyContext();
strategyContext.setStrategyAbstract(new StrategyBus());
price = strategyContext.price(km);
Log.e(TAG, "bus price = " + price);
strategyContext.setStrategyAbstract(new StrategySubway());
price = strategyContext.price(km);
Log.e(TAG, "subway price = " + price);
测试结果
2020-03-29 13:59:17.441 8541-8541/? E/MainActivity: bus price = 20.0
2020-03-29 13:59:17.441 8541-8541/? E/MainActivity: subway price = 40.0
策略模式+反射,优化if-else
if-else 过多时代码就会变得臃肿并且要修改已有的代码,这就违背了对修改关闭对扩展开放的设计原则,这种情况下就引出了策略模式。
if(a){
//dosomething
}else if (b){
//doshomething
}else if(c){
//doshomething
} else{
doshomething
}
左边是一个常规的策略模式,将这几种情况分别封装到各自的类中。
右边定义了Strategy枚举类,其中包含所有Strategy的信息,StrategySelector中获取到Strategy中的所有策略,然后根据传入的参数创建对应的策略对象。
方案一,利用反射,通过类名创建类对象
利用反射,通过类名创建类对象。以供StrategyContext使用
package com.zhangyu.StrategyIfElse.context;
import com.zhangyu.StrategyIfElse.strategy.IStrategy;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
public class StrategySelector {
public enum Strategy {
Bronze("青铜用户", "com.zhangyu.StrategyIfElse.strategy.StrategyBronze"),
Silver("白银用户", "com.zhangyu.StrategyIfElse.strategy.StrategySilver"),
Gold("黄金用户", "com.zhangyu.StrategyIfElse.strategy.StrategyGold");
String description;
String className;
Strategy(String description, String className) {
this.description = description;
this.className = className;
}
public String getDescription() {
return description;
}
public String getClassName() {
return className;
}
public static Map<String, String> getAllClass() {
Map<String, String> map = new HashMap<>();
for (StrategySelector.Strategy strategy :
StrategySelector.Strategy.values()) {
map.put(strategy.getDescription(), strategy.getClassName());
}
return map;
}
}
public static IStrategy getInstance(String desc) {
//得到所有的策略类
Map<String, String> allClass = Strategy.getAllClass();
//得到需要的策略类类名
String className = allClass.get(desc);
//根据类名创建类对象
IStrategy strategy = null;
try {
strategy = (IStrategy) Class.forName(className).getDeclaredConstructor().newInstance();
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
e.printStackTrace();
}
return strategy;
}
}
方案二:不使用反射
package com.zhangyu.StrategyIfElse.context;
import com.zhangyu.StrategyIfElse.strategy.IStrategy;
import com.zhangyu.StrategyIfElse.strategy.StrategyBronze;
import com.zhangyu.StrategyIfElse.strategy.StrategyGold;
import com.zhangyu.StrategyIfElse.strategy.StrategySilver;
import java.util.HashMap;
import java.util.Map;
public class StrategySelector2 {
public static IStrategy getInstance(String desc) {
//得到所有的策略类
Map<String, IStrategy> strategyMap = new HashMap<>();
strategyMap.put("青铜用户", new StrategyBronze());
strategyMap.put("白银用户", new StrategySilver());
strategyMap.put("黄金用户", new StrategyGold());
return strategyMap.get(desc);
}
}
Main
package com.zhangyu.StrategyIfElse;
import com.zhangyu.StrategyIfElse.context.StrategyContext;
import com.zhangyu.StrategyIfElse.context.StrategySelector;
import com.zhangyu.StrategyIfElse.strategy.IStrategy;
public class Main {
public static void main(String[] args) {
//服务器返回来的信息
String vipLevel = "白银用户";
//选择具体的策略
IStrategy strategy = StrategySelector.getInstance(vipLevel);
//执行对应的操作
StrategyContext strategyContext = new StrategyContext(strategy);
strategyContext.execute();
}
}
剩下的部分是常规的策略模式
IStrategy接口
package com.zhangyu.StrategyIfElse.strategy;
public interface IStrategy {
void doSomething();
}
接口的实现类
package com.zhangyu.StrategyIfElse.strategy;
public class StrategyGold implements IStrategy{
@Override
public void doSomething() {
System.out.println("黄金用户的操作");
}
}
上下文
package com.zhangyu.StrategyIfElse.context;
import com.zhangyu.StrategyIfElse.strategy.IStrategy;
public class StrategyContext {
IStrategy strategy;
public StrategyContext(IStrategy strategy) {
this.strategy = strategy;
}
public void execute(){
strategy.doSomething();
}
}