策略模式概念
1 使用场景
比较器,旅行路线,固定算法,结算支付方式,登录等,根据用户的需求处理数据的时候需要对算法做出选择(固定的算法,不需要改变的),客户已经有选择,不需要知道算法的具体细节。
- 针对同一类型问题的多种处理方式,仅仅是具体行为有差别时;
- 需要安全地封装多种同一类型的操作时;
- 出现同一抽象类有多个子类,而又需要使用 if-else 或者 switch-case 来选择具体子类时。
通常会结合抽象工厂模式进行使用。
2 策略模式涉及到的角色
- 环境(Context)角色:持有一个Strategy的引用。
- 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
- 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
3 基本特点
- 最终执行结果是固定的
- 执行过程和执行逻辑不一样
策略工厂实现
支付功能枚举类
将所有实现支付接口的类,将其码值,名称,及实现对象放入到枚举类中
策略工程类
public enum StrategyEnmu {
/**
* 支付方式
*/
AliPay("1","AliPay",new AliPay()),
JDPay("2","JDPay",new JDPay()),
WechatPay("3","WechatPay",new WechatPay());
//值
private String value;
private String payType;
private Payment payment;
public String getValue() {
return value;
}
public String getPayType() {
return payType;
}
public Payment getPayment() {
return payment;
}
StrategyEnmu(String value, String payType, Payment payment) {
this.value = value;
this.payType = payType;
this.payment = payment;
}
}
使用@Component将类在启动服务时注入容器
@PostConstruct,在 StrategyFactoryc注入容器之前调用register方法,遍历枚举类中的所有变量,并将支付名称作为key,支付对象作为value作为值,放入到hashmap容器中。
@Component
public class StrategyFactory {
public static Map<String, Payment> paymentMap = new HashMap<>();
@PostConstruct
public static void register(){
for(StrategyEnmu a:StrategyEnmu.values()){
paymentMap.put(a.getPayType(), a.getPayment());
}
}
public static Payment getPayment(String payValue){
return paymentMap.get(payValue);
}
}
抽象策略:支付接口
public interface Payment {
public void pay();
}
具体策略:
@Service
public class JDPay implements Payment {
@Override
public void pay() {
System.out.println("京东支付");
}
}
@Service
public class AliPay implements Payment {
@Override
public void pay() {
System.out.println("支付宝支付");
}
}
@Service
public class WechatPay implements Payment {
@Override
public void pay() {
System.out.println("微信支付");
}
}
测试
@RequestMapping("/strategy")
public void PayOrder (@RequestParam String payType){
System.out.println(payType);
Payment payment = paymentMap.get(payType);
payment.pay();
}
策略工厂优化
可以在抽象策略中添加一个获取支付类型名称的抽象方法。
在策略工厂类中用@Autowired,动态将抽象策略下的具体策略注入hashmap容器。
public interface Payment {
public void pay();
public String getPayType();
}
@Component
public class StrategyFactory1 {
private static Map<String, Payment> paymentMaps = new HashMap<>();
@Autowired
public static void register(List<Payment> payments){
for(Payment p:payments){
paymentMaps.put(p.getPayType(),p);
}
}
public static Payment getPayment(String payValue){
return paymentMaps.get(payValue);
}
}
策略模式的真正意义
策略模式不仅只是上边实现的那样,如果仔细观察会发现,上述代码是在不复用代码的情况下设计。
真正的策略模式是基于委派和组合实现的。
定义一个抽象类
将鸭子飞和叫的行为委派给另外两个接口,FlyBehavior、QuackBehavior
public abstract class Duck {
public FlyBehavior flyBehavior;
public QuackBehavior quackBehavior;
public Duck(){}
public abstract void display();
public void performFly(){
flyBehavior.fly();
}
public void performQuack(){
quackBehavior.quack();
}
public void swim(){
System.out.println("All ducks float,even decoys");
}
}
实现飞和叫的两个委派接口
public interface FlyBehavior {
public void fly();
}
public interface QuackBehavior {
public void quack();
}
具体的实现类
public class FlyWithWings implements FlyBehavior{
@Override
public void fly() {
System.out.println("I'm flying");
}
}
public class FlyNoWay implements FlyBehavior{
@Override
public void fly() {
System.out.println("I can't fly");
}
}
public class Squeak implements QuackBehavior {
@Override
public void quack() {
System.out.println("Squeak");
}
}
public class MuteQuack implements QuackBehavior {
@Override
public void quack() {
System.out.println("<<Silence>>");
}
}
public class Quack implements QuackBehavior {
@Override
public void quack() {
System.out.println("Quack");
}
}
具体的鸭子在构造方法中对鸭子具体行为进行组合
public class MallardDuck extends Duck {
public MallardDuck(){
quackBehavior=new Quack();
flyBehavior=new FlyWithWings();
}
@Override
public void display() {
System.out.println("I'm a real mallard duck");
}
}
测试类
public class MiniDuckTest {
public static void main(String[] args){
Duck mallard = new MallardDuck();
mallard.performFly();
mallard.performQuack();
}
}