【设计模式系列笔记】策略模式

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
简介: 策略模式(Strategy Pattern)是一种行为设计模式,它定义了一系列的算法,将每个算法封装起来,并且使它们可以互相替换。策略模式使得算法可以独立于客户端而变化。

1. 策略模式介绍

策略模式(Strategy Pattern)是一种行为设计模式,它定义了一系列的算法,将每个算法封装起来,并且使它们可以互相替换。策略模式使得算法可以独立于客户端而变化。

在Java中,策略模式通常涉及两个主要角色:上下文(Context)和策略(Strategy)。上下文负责维护一个对策略对象的引用,而策略定义了一个接口或抽象类,包含了具体算法的实现。

2. 关键思想

策略模式的关键思想是定义一系列算法,将每个算法封装起来,使它们可以相互替换,而且使得客户端代码独立于具体的算法实现。以下是策略模式的一些关键思想:

  1. 定义一组算法接口或抽象类: 策略模式首先需要定义一个接口或抽象类,它声明了一组算法的方法。这个接口或抽象类通常被称为"策略"。
  2. 实现具体的策略类: 针对上述的接口或抽象类,实现一组具体的策略类,每个类都包含了算法的具体实现。
  3. 在上下文中使用策略: 上下文是使用算法的地方,它包含一个对策略的引用。上下文可以在运行时更改所使用的策略,从而影响其行为。
  4. 使策略可以相互替换: 策略模式的核心是使得不同的算法可以相互替换,而不影响客户端的代码。这通过将策略作为对象传递给上下文来实现。
  5. 封装变化: 策略模式将不同的算法封装在独立的策略类中,从而使得每个算法的变化不会影响到其他算法。这有助于维护和扩展。
  6. 客户端与算法的解耦: 策略模式实现了客户端与具体算法的解耦,使得客户端可以独立于具体算法的变化而变化。

策略模式常用于需要在运行时选择算法的场景,或者当有多个类似的类,它们之间的区别仅在于它们的行为时。通过使用策略模式,可以更灵活地管理和扩展算法,同时保持代码的清晰度和可维护性。

3. 实现方式

策略模式的实现方式通常涉及以下几个步骤:

  1. 定义策略接口或抽象类: 声明一组算法的接口或抽象类,这个接口或抽象类就是策略,其中包含了算法的方法。
  2. 实现具体的策略类: 针对策略接口或抽象类,实现一组具体的策略类,每个类都包含了算法的具体实现。
  3. 创建上下文类: 上下文类负责维护一个对策略对象的引用,并提供一个接口供客户端设置和使用策略。上下文类中通常包含了调用策略的方法。
  4. 客户端使用上下文类: 客户端通过创建上下文类的实例,并通过设置不同的策略对象来实现不同的算法。
// 定义策略接口
interface PaymentStrategy {
    double calculateTotal(double orderAmount);
}
// 具体策略实现 - 支付宝支付
class AlipayPaymentStrategy implements PaymentStrategy {
    @Override
    public double calculateTotal(double orderAmount) {
        // 具体的算法实现
        // 假设支付宝支付有折扣
        return orderAmount * 0.9;
    }
}
// 具体策略实现 - 微信支付
class WeChatPaymentStrategy implements PaymentStrategy {
    @Override
    public double calculateTotal(double orderAmount) {
        // 具体的算法实现
        // 假设微信支付无折扣
        return orderAmount;
    }
}
// 上下文类
class OrderContext {
    private PaymentStrategy paymentStrategy;
    // 设置策略
    public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
        this.paymentStrategy = paymentStrategy;
    }
    // 根据当前策略计算总价
    public double calculateTotal(double orderAmount) {
        return paymentStrategy.calculateTotal(orderAmount);
    }
}
// 客户端代码
public class StrategyPatternExample {
    public static void main(String[] args) {
        OrderContext orderContext = new OrderContext();
        // 使用支付宝支付策略
        orderContext.setPaymentStrategy(new AlipayPaymentStrategy());
        double totalWithAlipay = orderContext.calculateTotal(100.0);
        System.out.println("支付宝支付: " + totalWithAlipay);
        // 使用微信支付策略
        orderContext.setPaymentStrategy(new WeChatPaymentStrategy());
        double totalWithWeChat = orderContext.calculateTotal(100.0);
        System.out.println("微信支付: " + totalWithWeChat);
    }
}

在上面的例子中,PaymentStrategy是策略接口,AlipayPaymentStrategyWeChatPaymentStrategy是具体的策略实现。OrderContext是上下文类,它持有一个对策略的引用,并通过calculateTotal方法调用具体的策略来计算总价。客户端可以根据需要设置不同的支付策略。

要点:

  1. 定义清晰的策略接口或抽象类: 策略接口或抽象类应该定义算法的方法,确保各个具体策略都实现了相同的接口,以便它们可以互相替换。
  2. 实现具体的策略类: 对于每个算法,创建一个具体的策略类,并在这些类中提供具体的算法实现。
  3. 上下文类的存在: 引入上下文类来维护对策略对象的引用,并在运行时设置所需的具体策略。
  4. 客户端选择策略: 客户端负责选择并设置适当的策略,以满足特定的需求。
  5. 封装变化: 策略模式的目标是封装不同算法的变化,使得这些变化不会影响到客户端的代码。

注意事项:

  1. 选择合适的场景: 策略模式适用于有多个相关算法,并且需要在运行时动态选择其中一个算法的情况。如果系统中只有一个算法,或者算法不经常变化,可能没有必要使用策略模式。
  2. 过度使用: 不要过度使用策略模式,否则可能导致类的数量过多,增加系统的复杂性。只有在确实需要支持多个算法,并且这些算法可以相互替换时,才使用策略模式。
  3. 运行时切换策略: 一个重要的优势是能够在运行时切换策略。确保上下文类的接口和方法能够支持动态切换不同的策略。
  4. 性能考虑: 在一些性能敏感的场景,动态切换策略可能会引入一些开销。在这种情况下,需要仔细评估性能影响。
  5. 与工厂模式结合使用: 有时候,策略模式和工厂模式可以结合使用,通过工厂模式创建具体的策略对象,提供更灵活的对象创建方式。

总的来说,策略模式是一种强大的设计模式,能够使得代码更具有扩展性和灵活性,但在使用时需要权衡设计的复杂性和应用场景的实际需求。

优点:

  1. 灵活性和可扩展性: 策略模式允许在运行时选择算法,提供了灵活性。新的算法可以通过实现新的策略类并注入到上下文中,而不需要修改客户端代码。
  2. 避免使用多重条件语句: 策略模式可以避免使用大量的条件语句来选择不同的算法,使得代码更加清晰、简洁。
  3. 算法独立性: 算法被封装在独立的策略类中,使得这些算法可以独立于上下文类而变化,提高了代码的可维护性和可复用性。
  4. 易于测试: 策略模式使得单元测试变得更容易,因为每个算法都有自己的类,可以独立测试。

缺点:

  1. 类数量增多: 使用策略模式会导致系统中类的数量增加,每个具体策略都需要一个单独的类,可能会使得类的管理和维护变得复杂。
  2. 客户端需要知道所有的策略: 客户端需要了解所有的策略类,并在使用时选择适当的策略,这可能增加了客户端的复杂性。
  3. 上下文对策略的了解: 上下文类需要了解所有的策略,这可能导致上下文类的职责较重,违反了开闭原则。

应用场景:

  1. 算法经常变化: 当一个系统的算法需要经常切换时,使用策略模式可以方便地在运行时选择不同的算法。
  2. 避免使用多重条件语句: 当一个类有很多条件语句来选择不同的行为时,使用策略模式可以提高代码的可读性和可维护性。
  3. 相似行为的不同实现: 当类的相似行为有不同的实现时,可以使用策略模式将这些行为抽象成策略,实现不同的具体策略类。
  4. 需要提供多种算法变体: 如果一个类的算法有多个变体,并且这些变体经常需要切换,策略模式是一个不错的选择。

总的来说,策略模式在需要灵活处理算法的场景中是非常有用的,但在使用时需要根据实际情况权衡其优缺点。

目录
相关文章
|
14天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
160 37
|
14天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑】设计模式——原型模式
对比原型模式和传统方式的实现思路、代码方案、优缺点,阐述原型模式的使用场景,以及深拷贝、浅拷贝等相关概念,并扩展原型模式在Spring源码中的应用。
【Java笔记+踩坑】设计模式——原型模式
|
3月前
|
设计模式 算法
策略模式-大话设计模式
策略模式-大话设计模式
|
2天前
|
设计模式 运维 算法
Java设计模式-策略模式(15)
Java设计模式-策略模式(15)
|
9天前
|
设计模式 算法 PHP
PHP中的设计模式:策略模式的深度解析
在PHP开发中,策略模式是一种行为设计模式,它允许你在运行时根据不同情况选择不同的算法或行为。本文将深入探讨策略模式的定义、结构、使用场景以及在PHP中的实现方法,并通过实例展示如何在PHP项目中应用策略模式来提高代码的灵活性和可维护性。
|
4月前
|
设计模式 算法 Java
Java一分钟之-设计模式:策略模式与模板方法
【5月更文挑战第17天】本文介绍了策略模式和模板方法模式,两种行为设计模式用于处理算法变化和代码复用。策略模式封装不同算法,允许客户独立于具体策略进行选择,但需注意选择复杂度和过度设计。模板方法模式定义算法骨架,延迟部分步骤给子类实现,但过度抽象或滥用继承可能导致问题。代码示例展示了两种模式的应用。根据场景选择合适模式,以保持代码清晰和可维护。
81 1
|
10天前
|
设计模式 人工智能 算法
PHP中的设计模式:策略模式的深入解析与实践软件测试中的人工智能革命:提升效率与准确性的新篇章
在PHP开发中,理解并运用设计模式是提升代码质量和可维护性的重要途径。本文聚焦于策略模式(Strategy Pattern),一种行为型设计模式,它允许在运行时选择算法或业务规则。通过本文,我们将深入探讨策略模式的定义、结构、使用场景以及如何在PHP项目中有效地实现和利用策略模式。不同于性能优化等技术性摘要,本文着重于提供对策略模式全面而实用的理解,助力开发者编写出更加灵活和可扩展的应用程序。 本文深入探讨了人工智能在软件测试领域的应用,揭示了其如何显著提高测试过程的效率和准确性。通过实际案例分析,展示了AI技术在自动化测试、缺陷检测及结果分析中的关键作用,并讨论了实施AI测试策略时面临的挑
16 3
|
14天前
|
设计模式 算法 PHP
PHP中的设计模式:策略模式的深度解析
在本文中,我们将深入探讨PHP编程中的策略模式,这是一种行为型设计模式,用于定义一系列算法,将每个算法封装起来,并使它们可以互换。通过详细讲解策略模式的概念、结构以及在PHP中的实现方式,我们希望能够帮助读者更好地理解和应用这一设计模式,提升代码的灵活性和可维护性。
24 1
|
2天前
|
设计模式 存储 算法
PHP中的设计模式:策略模式的深入解析与应用在软件开发的浩瀚海洋中,PHP以其独特的魅力和强大的功能吸引了无数开发者。作为一门历史悠久且广泛应用的编程语言,PHP不仅拥有丰富的内置函数和扩展库,还支持面向对象编程(OOP),为开发者提供了灵活而强大的工具集。在PHP的众多特性中,设计模式的应用尤为引人注目,它们如同精雕细琢的宝石,镶嵌在代码的肌理之中,让程序更加优雅、高效且易于维护。今天,我们就来深入探讨PHP中使用频率颇高的一种设计模式——策略模式。
本文旨在深入探讨PHP中的策略模式,从定义到实现,再到应用场景,全面剖析其在PHP编程中的应用价值。策略模式作为一种行为型设计模式,允许在运行时根据不同情况选择不同的算法或行为,极大地提高了代码的灵活性和可维护性。通过实例分析,本文将展示如何在PHP项目中有效利用策略模式来解决实际问题,并提升代码质量。
|
29天前
|
设计模式 缓存 算法
揭秘策略模式:如何用Java设计模式轻松切换算法?
【8月更文挑战第30天】设计模式是解决软件开发中特定问题的可重用方案。其中,策略模式是一种常用的行为型模式,允许在运行时选择算法行为。它通过定义一系列可互换的算法来封装具体的实现,使算法的变化与客户端分离。例如,在电商系统中,可以通过定义 `DiscountStrategy` 接口和多种折扣策略类(如 `FidelityDiscount`、`BulkDiscount` 和 `NoDiscount`),在运行时动态切换不同的折扣逻辑。这样,`ShoppingCart` 类无需关心具体折扣计算细节,只需设置不同的策略即可实现灵活的价格计算,符合开闭原则并提高代码的可维护性和扩展性。
39 2