策略模式实战

策略模式

前言

实习的时候,在写一个业务的时候,需要判断操作的对象以及操作的类型,当时是有两种对象,它们都有两种操作类型,所以很自然的就使用了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();  
}

image.png

没有具体的结合业务,看起来可能有些抽象,但是总的来说,使用了策略模式后,如果我们想要新增一个策略,只需要再写一个实现了 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();  
}

这样其实工厂类还是不符合开闭原则,暂时没找到好的法子,后面遇见了来补充。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYHKDhPt' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片