JAVA设计模式之【策略模式】

JAVA设计模式之【策略模式】,第1张

JAVA设计模式之【策略模式】

工厂模式是解耦对象的创建和使用,观察者模式是解耦观察者和被观察者。策略模式跟两者类似,也能起到解耦的作用,解耦的是策略的定义、创建、使用这三部分。
通常的使用方式
**

1.策略定义

**
一个策略接口和一组实现这个接口的策略类。因为所有的策略类都实现相同的接口,所以,客户端代码基于接口而非实现编程,可以灵活地替换不同的策略。

public interface Strategy {
  void algorithm();
}

public class StrategyA implements Strategy {
  @Override
  public void  algorithm() {
    //具体的算法...
  }
}

public class StrategyB implements Strategy {
  @Override
  public void  algorithm() {
    //具体的算法...
  }
}

2.策略创建
一组策略,使用时一般通过type来判断创建哪个策略。
工厂封装创建逻辑,对客户端屏蔽创建细节

public class StrategyFactory {
  private static final Map strategies = new HashMap<>();

  static {
    strategies.put("A", new StrategyA());
    strategies.put("B", new StrategyB());
  }

  public static Strategy getStrategy(String type) {
    if (type == null || type.isEmpty()) {
      throw new IllegalArgumentException("type should not be empty.");
    }
    return strategies.get(type);
  }
}

如果策略类是无状态的,不包含成员变量,只是纯粹的算法实现,这样的策略对象是可以被共享使用的,使用map缓存
如果策略类是有状态的,根据业务场景的需要,我们希望每次从工厂方法中,获得的都是新创建的策略对象,而不是缓存好可共享的策略对象,则:

public class StrategyFactory {
  public static Strategy getStrategy(String type) {
    if (type == null || type.isEmpty()) {
      throw new IllegalArgumentException("type should not be empty.");
    }

    if (type.equals("A")) {
      return new StrategyA();
    } else if (type.equals("B")) {
      return new StrategyB();
    }

    return null;
  }
}

3.策略的使用
最常见的是运行时动态确定使用哪种策略,这也是策略模式最典型的应用场景。
Strategy strategy=StrategyFactory.getStrategy(type)

简便的使用方式
1.策略定义

public interface Strategy {
  //用来匹配策略
  boolean match(String type);  
  String algorithm();
}

public class StrategyA implements Strategy {
    @Override
    public boolean match(String type) {
        return "A".equals(type);
    }
    
    @Override
    public String  algorithm() {
        //具体的算法...
        return "this is A";
    }
}

public class StrategyB implements Strategy {
    @Override
    public boolean match(String type) {
        return "B".equals(type);
    }
    
    @Override
    public String  algorithm() {
        //具体的算法...
        return "this is B";
    }
}

//默认执行的策略
public class DefaultStrategy implements Strategy {

    @Override
    public boolean match(String type) {
        return false;
    }

    @Override
    public String algorithm() {
        return "this is 默认方法";
    }
}

2.策略使用

    @Autowired
    private List strategyList;

    @Autowired
    private DefaultStrategy defaultStrategy;

    @Test
    public void test_Strategy(){
       String type="A";
       //直接使用lamba表达式,match匹配执行Strategy
       String result=strategyList.stream()
           .filter(strategy -> strategy.match(type))
           .findFirst()
           .orElse(defaultStrategy)
           .algorithm();
    }

输出result="this is A";

实战代码优化
原代码写法

if (TradeChannelTypeEnum.RAPID_SEND.getType() == tradeChannel) {
    result = rapidSendInvSaleMatch.match(dbEntity, EnumsMatchType.NORMAL.getType(), tradeChannel..);
} else if (TradeChannelTypeEnum.FLASH_SEND.getType() == tradeChannel) {
    result = flashSendInvSaleMatch.match(dbEntity, EnumsMatchType.NORMAL.getType(), tradeChannel..);
} else if (TradeChannelTypeEnum.BRAND_OFFER.getType() == tradeChannel) {
    result = brandOfferInvSaleMatch.match(dbEntity, EnumsMatchType.NORMAL.getType(), tradeChannel..);
} else {
    result = defaultInvSaleMatch.match(dbEntity, EnumsMatchType.NORMAL.getType(), tradeChannel..);
}

可以看出,在业务增加的情况下,不断增加if-else,增加 InvSaleMatch service。根据不同的tradeChannel选择不同的 **InvSaleMatch (**InvSaleMatch都继承自AbsInvSaleMatch),可直接使用策略模式。

优化之后

//AbsInvSaleMatch增加 tradeChannelMatch方法
 boolean tradeChannelMatch(int tradeChannel);
 //各个InvSaleMatch 实现类里判断tradeChannel,用来替代之前代码里的if判断
@Autowired
private List saleMatchList;

result = saleMatchList.stream().filter(hander -> hander.tradeChannelMatch(tradeChannel)).findFirst()
                    .orElse(defaultInvSaleMatch)
                    .match(dbEntity, EnumsMatchType.NORMAL, tradeChannel..);

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5719793.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-18

发表评论

登录后才能评论

评论列表(0条)

保存