Head first之策略模式

本文介绍了策略模式的概念及其在支付场景中的应用,通过枚举和工厂类实现支付策略的选择。同时,展示了如何优化策略工厂,以减少代码冗余。此外,还探讨了策略模式在鸭子行为模拟中的使用,通过委派和组合实现了不同鸭子飞行和叫声的策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

策略模式概念

1 使用场景

比较器,旅行路线,固定算法,结算支付方式,登录等,根据用户的需求处理数据的时候需要对算法做出选择(固定的算法,不需要改变的),客户已经有选择,不需要知道算法的具体细节。

  1. 针对同一类型问题的多种处理方式,仅仅是具体行为有差别时;
  2. 需要安全地封装多种同一类型的操作时;
  3. 出现同一抽象类有多个子类,而又需要使用 if-else 或者 switch-case 来选择具体子类时。

通常会结合抽象工厂模式进行使用。

2 策略模式涉及到的角色

  1. 环境(Context)角色:持有一个Strategy的引用。
  2. 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
  3. 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。

3 基本特点

  1. 最终执行结果是固定的
  2. 执行过程和执行逻辑不一样

策略工厂实现

支付功能枚举类

将所有实现支付接口的类,将其码值,名称,及实现对象放入到枚举类中

策略工程类

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();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

睿智的小薛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值