策略模式:让你的代码灵活应对不同场景

写在前面

如果你正在为代码的可扩展性和可维护性感到烦恼,策略模式可以成为你的得力助手。本篇技术文章详细介绍了策略模式的核心原理和实战应用,帮助你解决在程序设计中所面临的挑战。无论你是初学者还是有一定经验的开发者,这篇文章都能够为你提供有益的知识和实用的技巧,值得一读!

前言

用于处理类或对象的组合的结构型的设计模式已经输出完毕:

适配器模式揭秘:让不兼容的组件完美协同

剖析装饰器模式:让你的代码更灵活、可扩展

探秘代理模式:核心原理与应用实践

优雅的程序设计:掌握门面模式的奥秘

桥梁模式:解耦抽象与实现的秘诀

组合模式揭秘:如何构建可扩展的树形结构

提升软件性能的秘密武器:揭秘实战中的享元模式

从这篇文章开始来盘一盘行为型设计模式,那么行为型的设计模式有哪些呢?行为型模式是用于描述类或对象怎样交互以及怎样分配职责,共十一种,包括策略模式、模版方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

什么是策略模式

策略模式是一种行为型设计模式,它定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。策略模式的主要目的是将算法的行为和环境分开,将一系列算法封装在策略类中,并在运行时根据客户端的需求选择相应的算法。策略模式适用于需要使用多种算法,且算法之间可以相互替换的情况。在策略模式中,算法的变化不会影响到使用算法的客户端。

策略模式的核心原理

策略模式是一种行为设计模式,其核心原理是将可以相互替换的算法封装成独立的类,并使它们能够互相之间替换,以使得算法的变化独立于使用算法的客户端。

策略模式主要包括三个核心角色:

  1. Context(上下文):这个角色是策略模式中的重要组成部分,通常用于存储和传递策略对象,以及处理策略对象的交互逻辑。上下文对象在客户端的请求下,会调用合适的策略对象来执行相应的操作。
  2. Strategy(策略):这个角色通常是一个接口,用于定义各种策略对象的共同方法。具体策略对象实现这个接口,并包含具体的算法实现。策略对象不持有任何上下文对象的状态,这样保证了策略对象的可复用性。
  3. ConcreteStrategy(具体策略):这个角色是实现策略接口的具体类,包含了具体的算法实现。具体策略对象通常会持有上下文对象的状态,以便在执行算法时能够访问和修改这些状态。

这三个核心角色共同实现了策略模式的核心思想:将算法与使用算法的客户端分离,使算法可以独立于客户端而变化。

策略模式如何实现

需求描述

很多购物网站都有会员业务,不同等级的会员可以享受不同程度的优惠,这里假设某会员业务系统的会员等级有非会员、初级会员、中级会员、高级会员四个等级,其中非会员在支付的时候需要全额支付 ,初级会员可以享受8折优惠,中级会员可以享受7折优惠,高级会员可以享受5折优惠,如果需要写一个支付接口,需要怎么实现呢?

实现方案

类似这样的业务模型,是比较适合使用策略模式的,但是如果仅仅使用策略模式是没有办法在主业务流程中完全避免if else的判断的,如果从实际业务出发,可以把简单工厂模式和策略模式结合起来使用。策略模式只负责定义不同的优惠策略,而简单工厂模式,负责根据不同的会员,生产出不同的具体优惠策略。具体怎么做呢?

1、定义抽象的支付策略接口:PayStrategy.java;

java 复制代码
/**
 * 支付策略接口
 */
public interface PayStrategy {
    /**
     * 实际支付金额计算
     * @param money
     */
    Double compute(Double money);
}

2、定义具体的支付策略类:Level0Streategy.java、Level1Streategy.java、Level2Streategy.java、Level3Streategy.java

java 复制代码
/**
 * 非会员计费策略
 */
public class Level0Strategy implements PayStrategy{
    @Override
    public Double compute(Double money) {
        System.out.println("非会员开始计费");
        return money;
    }
}
java 复制代码
/**
 * 初级会员计费策略
 */
public class Level1Strategy implements PayStrategy{
    @Override
    public Double compute(Double money) {
        System.out.println("初级会员开始计费");
        return money*0.8;
    }
}
java 复制代码
/**
 * 中级会员计费策略
 */
public class Level2Strategy implements PayStrategy{
    @Override
    public Double compute(Double money) {
        System.out.println("中级会员开始计费");
        return money*0.7;
    }
}
java 复制代码
/**
 * 高级会员计费策略
 */
public class Level3Strategy implements PayStrategy{
    @Override
    public Double compute(Double money) {
        System.out.println("高级会员开始计费");
        return money*0.5;
    }
}

3、定义用于存储和传递策略的上下文:StreateContext.java

java 复制代码
/**
 * 支付策略上下文
 */
public class StrategyContent {
    private PayStrategy payStrategy;

    public StrategyContent(PayStrategy payStrategy) {
        this.payStrategy = payStrategy;
    }

    /**
     * 支付方法
     * @param money
     * @return
     */
    public Double pay(Double money){
        return this.payStrategy.compute(money);
    }
}

4、定义策略工厂类,用于生产具体的策略:PayStreategyFactory.java

java 复制代码
/**
 * 策略工厂
 */
public class PayStrategyFactory {

    public static PayStrategy getStrategy(Member member){
        PayStrategy payStrategy;
        switch (member.getLevel()){
            case "初级":
                payStrategy=new Level1Strategy();
                break;
            case "中级":
                payStrategy=new Level2Strategy();
                break;
            case "高级":
                payStrategy=new Level3Strategy();
                break;
            default:
                payStrategy=new Level0Strategy();
                break;
        }
        return payStrategy;
    }
}

5、编写客户端:,模拟不同的用户进行支付:Test.java

java 复制代码
@Data
@AllArgsConstructor
public class Member {
    /**
     * 会员姓名
     */
    private String name;
    /**
     * 会员等级:非会员、初级、中级、高级
     */
    private String level;
    /**
     * 支付金额
     */
    private Double pay;
}
java 复制代码
public class Test {
    public static void main(String[] args) {
        Member member = new Member("小明", "初级", 100.00);
        PayStrategy strategy = PayStrategyFactory.getStrategy(member);
        StrategyContent strategyContent = new StrategyContent(strategy);
        Double pay = strategyContent.pay(member.getPay());
        System.out.println(member.getName() + "应支付金额:" + member.getPay() + ",实际支付金额:" + pay);
        member = new Member("小红", "中级", 100.00);
        strategy = PayStrategyFactory.getStrategy(member);
        strategyContent = new StrategyContent(strategy);
        pay = strategyContent.pay(member.getPay());
        System.out.println(member.getName() + "应支付金额:" + member.getPay() + ",实际支付金额:" + pay);
        member = new Member("铁蛋", "高级", 100.00);
        strategy = PayStrategyFactory.getStrategy(member);
        strategyContent = new StrategyContent(strategy);
        pay = strategyContent.pay(member.getPay());
        System.out.println(member.getName() + "应支付金额:" + member.getPay() + ",实际支付金额:" + pay);
        member = new Member("李刚", "非会员", 100.00);
        strategy = PayStrategyFactory.getStrategy(member);
        strategyContent = new StrategyContent(strategy);
        pay = strategyContent.pay(member.getPay());
        System.out.println(member.getName() + "应支付金额:" + member.getPay() + ",实际支付金额:" + pay);
    }
}

策略模式的适用场景

  1. 不同业务逻辑:在同一个业务逻辑中,可能会存在不同的策略或算法。例如,在电商网站中,可以根据不同的促销策略对商品进行不同的定价。在这种情况下,可以使用策略模式来封装不同的促销策略,并在运行时根据需要选择合适的策略。
  2. 数据排序策略:在处理大量数据时,可能需要使用不同的排序算法。例如,冒泡排序、选择排序、插入排序和二叉树排序等。在这种情况下,可以使用策略模式来定义不同的排序策略,并在运行时根据需要选择合适的策略。
  3. 算法切换:在某些情况下,可能需要根据不同的条件切换不同的算法。例如,在进行实时计算时,可能需要根据不同的输入数据选择不同的计算算法。在这种情况下,可以使用策略模式来封装不同的算法,并在运行时根据需要选择合适的算法。
  4. 行为切换:在系统中,可能需要根据不同的条件切换不同的行为。例如,在一个游戏中,可能需要根据不同的关卡选择不同的游戏策略。在这种情况下,可以使用策略模式来封装不同的游戏策略,并在运行时选择合适的行为。

总之,策略模式的应用场景非常广泛,可以用于处理不同业务逻辑、数据排序、算法切换和行为切换等方面。通过使用策略模式,我们可以将算法或行为的变化和具体实现细节分离出来,使得代码更加灵活、易于维护和扩展。

总结

优点:

  1. 避免使用多重条件语句:策略模式通过使用策略类和上下文对象来避免使用多重条件语句,如if-else语句或switch-case语句。通过将算法的行为封装到策略类中,并在运行时根据客户端的需求选择相应的算法,策略模式使得代码更加简洁、易于维护和扩展。
  2. 提供可重用的算法族:策略模式通过定义抽象策略类和具体策略类,提供了一系列的算法实现。这些算法可以在不同的上下文中重复使用,通过组合和替换不同的策略对象来满足客户端的需求。
  3. 分离算法和客户端:策略模式将算法的实现和使用分离到具体的策略类和上下文对象中。客户端只需要与上下文对象进行交互,而不需要直接处理算法的实现细节。这种分离使得代码更加清晰、易于理解和维护。
  4. 支持对开闭原则的完美支持:策略模式可以在不修改原有代码的情况下,灵活地增加新的算法。通过定义新的策略类和上下文对象,可以轻松地将新的算法集成到现有系统中,满足新的需求。
  5. 将算法的使用放到环境类中:策略模式将算法的使用放到上下文对象中,而算法的实现则移到具体策略类中。这种分离使得代码更加清晰、易于管理和扩展。
  6. 客户端必须理解所有策略算法的区别:策略模式要求客户端必须理解所有可用的策略算法的区别,以便在适当的时候选择合适的算法。这可能增加了客户端的复杂性和学习成本。

缺点

  1. 可能导致过多的策略类:策略模式可能导致创建过多的策略类,每个算法都对应一个策略类。这可能会增加系统的复杂性和维护成本。

总之,策略模式是一种行为型设计模式,它通过封装一系列可重用的算法实现,并将它们组合到不同的上下文中,实现了算法的行为和使用的分离。这种模式使得代码更加灵活、易于维护和扩展,同时支持在不修改原有代码的情况下增加新算法,从而提高了代码的灵活性和可维护性。

写在最后

感谢您阅读我们的技术文章!这篇文章详细介绍了策略模式的核心原理和实战应用,对于程序设计中所面临的问题提出了有益的解决方案。如果您觉得这篇文章有价值,请帮忙点赞和收藏,让更多人看到并受益。您的支持是我不断前行的动力和鼓励。再次感谢您的阅读和支持,期待我们的下一次相遇!

相关推荐
众拾达人5 分钟前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言
皓木.8 分钟前
Mybatis-Plus
java·开发语言
不良人天码星8 分钟前
lombok插件不生效
java·开发语言·intellij-idea
守护者17028 分钟前
JAVA学习-练习试用Java实现“使用Arrays.toString方法将数组转换为字符串并打印出来”
java·学习
源码哥_博纳软云30 分钟前
JAVA同城服务场馆门店预约系统支持H5小程序APP源码
java·开发语言·微信小程序·小程序·微信公众平台
禾高网络32 分钟前
租赁小程序成品|租赁系统搭建核心功能
java·人工智能·小程序
学会沉淀。37 分钟前
Docker学习
java·开发语言·学习
如若12339 分钟前
对文件内的文件名生成目录,方便查阅
java·前端·python
追逐时光者39 分钟前
免费、简单、直观的数据库设计工具和 SQL 生成器
后端·mysql
初晴~1 小时前
【Redis分布式锁】高并发场景下秒杀业务的实现思路(集群模式)
java·数据库·redis·分布式·后端·spring·