首先定义一组算法,将每一个算法封装起来,从而使它们可以相互切换
使用场景
同样的流程,需要执行不同的策略算法,传入不同策略,执行传入对应的策略算法
代码示例
public class Context {
private Strategy strategy
;
public Context(Strategy strategy
) {
this.strategy
= strategy
;
}
public void execute() {
strategy
.algorithmLgic();
}
}
public interface Strategy {
public void algorithmLgic();
}
public class ConcreteStrategyA implements Strategy {
@Override
public void algorithmLgic() {
System
.out
.println("执行算法A");
}
}
public class ConcreteStrategyB implements Strategy {
@Override
public void algorithmLgic() {
System
.out
.println("执行算法B");
}
}
public class App {
public static void main(String
[] args
) {
Context context
= new Context(new ConcreteStrategyA());
context
.execute();
}
}
角色说明
封装角色(Context):上层访问策略的入口,它持有着抽象策略对象的引用抽象策略角色(Strategy):提供接口或抽象类,定义策略组都需要拥有的方法和属性具体策略角色(ConcreteStrategyA、B):实现抽象策略,定义具体的算法逻辑
优缺点
优点
策略模式提供了管理相关算法族的方法。策略类的等级结构定义了⼀个算法或⾏为族。恰当使⽤继承可以把公共的代码移到⽗类⾥⾯,从⽽避免代码重复。避免使用if-else多重条件语句,因为策略模式下可以动态传入需要的算法对象
缺点
客户端(调用方)必须知道所有策略类,并自行决定使用哪种策略。这就意味着客户端必须理解所有算法的区别,以便需要的时候选择合适的算法。也就是说策略模式只适用于客户端知道所有算法的情况一个策略对应一个类,如果备选策略很多的话,类的数目就会很可观
高级用法
传入的策略对象可以替换为类的全路径,通过反射来动态获取策略算法
ContextReflect context
= new ContextReflect ("com.siqi.strategy.ConcreteStrategyA");
context
.execute();
public class ContextReflect {
Class
<?> clazz
= null
;
Object obj
= null
;
public CashContextReflect(String className
, Class
[] paramsType
, Object
[] parmas
){
try {
clazz
= Class
.forName(className
);
Constructor con
= clazz
.getConstructor(paramsType
);
obj
= con
.newInstance(parmas
);
} catch (InstantiationException | IllegalAccessException e
) {
e
.printStackTrace();
} catch (ClassNotFoundException e
) {
e
.printStackTrace();
} catch (IllegalArgumentException e
) {
e
.printStackTrace();
} catch (InvocationTargetException e
) {
e
.printStackTrace();
} catch (NoSuchMethodException e
) {
e
.printStackTrace();
} catch (SecurityException e
) {
e
.printStackTrace();
}
}
public double execute(){
return ((Strategy
)obj
).algorithmLogic();
}
}