策略模式
前言
实习的时候,在写一个业务的时候,需要判断操作的对象以及操作的类型,当时是有两种对象,它们都有两种操作类型,所以很自然的就使用了if-else来写:
if(obj.instanceOf(Obj1.class)) {
if(type == 0) {
// 第一种对象的操作 0 要做的业务
}else if(type == 1) {
// 第一种对象的操作 1 要做的业务
}
}else if(obj.instanceOf(Obj2.class)){
if(type == 0) {
// 第二种对象的操作 0 要做的业务
}else if(type == 1) {
// 第二种对象的操作 1 要做的业务
}
}
当时写完就觉得,这么写也太丑了吧~~
此外,这种写法完全就不符合开闭原则,如果又有一个新的对象,我就需要再来一个else if 分支;如果再来一个新的类型,我就需要在每个if分支中都加上这个操作类型对应的操作….想想都崩溃。
后面和同事聊天的时候,聊到他有一个支付的场景,需要对接不同的支付方式,采用了策略模式来简化 if-else,就想起了我写的这个业务场景,完全也可以使用策略模式,于是就进行了修改。
策略模式角色
抽象策略
顶层接口,用来管理不同的策略。
public interface AbstractStrategy {
//获取操作类型
String obtainDataType();
// 执行操作
void execute();
}
具体策略
是抽象策略接口的实现类,是具体的策略,比如上面例子就可以分成四种策略。
public class ConcentrateStrategyA implements AbstractStrategy{
@Override
public String obtainDataType() {
return "对象1的操作0";
}
@Override
public void execute() {
System.out.println("现在执行对象1的操作0");
}
}
public class ConcentrateStrategyA implements AbstractStrategy{
@Override
public String obtainDataType() {
return "对象1的操作1";
}
@Override
public void execute() {
System.out.println("现在执行对象1的操作1");
}
}
public class ConcentrateStrategyA implements AbstractStrategy{
@Override
public String obtainDataType() {
return "对象2的操作0";
}
@Override
public void execute() {
System.out.println("现在执行对象2的操作0");
}
}
public class ConcentrateStrategyA implements AbstractStrategy{
@Override
public String obtainDataType() {
return "对象2的操作1";
}
@Override
public void execute() {
System.out.println("现在执行对象2的操作1");
}
}
Context
客户端直接和Context交互,相当于解耦的作用。
public class Context {
private AbstractStrategy strategy;
public Context(AbstractStrategy strategy) {
this.strategy = strategy;
}
public void show() {
// 实际执行的策略
System.out.println(strategy.obtainDataType());
strategy.execute();
}
}
客户端
public void Client() {
System.out.println("#####策略1#####");
Context context = new Context(new ConcentrateStrategyA());
context.show();
// 策略2
System.out.println("#####策略2#####");
context = new Context(new ConcentrateStrategyB());
context.show();
// 策略3
System.out.println("#####策略3#####");
context = new Context(new ConcentrateStrategyC());
context.show();
// 策略4
System.out.println("#####策略4#####");
context = new Context(new ConcentrateStrategyD());
context.show();
}
没有具体的结合业务,看起来可能有些抽象,但是总的来说,使用了策略模式后,如果我们想要新增一个策略,只需要再写一个实现了 AbstractStrategy
接口的类就行。符合了开闭原则。
工厂模式解决不足
其实这种方案并没有消除if-else,我们还是需要判断前端传过来的具体类型参数来选择new哪个策略进行执行。
if(type == 1){
Context context = new Context(new ConcentrateStrategyA());
context.show();
}else if(type == 2) {
//...
}else if(type == 3) {
//....
}
这时候就可以将if-else或者switch-case转移到工厂中去。
Context变为工厂
public class StrategyFactory {
private static AbstractStrategy strategy;
public static AbstractStrategy selectStrategy(Integer type) {
switch (type) {
case 1:
strategy = new ConcentrateStrategyA();
break;
case 2:
strategy = new ConcentrateStrategyB();
break;
case 3:
strategy = new ConcentrateStrategyC();
break;
case 4:
strategy = new ConcentrateStrategyD();
break;
default:
throw new RuntimeException("不支持的类型");
}
return strategy;
}
}
客户端
@Test
public void Client() {
// 策略1
AbstractStrategy strategy = StrategyFactory.selectStrategy(1);
strategy.execute();
}
这样其实工厂类还是不符合开闭原则,暂时没找到好的法子,后面遇见了来补充。
© 版权声明
文章版权归作者所有,未经允许请勿转载,侵权请联系 admin@trc20.tw 删除。
THE END