设计模式-策略模式

文章目录

前言

当我们需要在不同情境下使用不同的算法或行为时,策略模式是一个非常有用的设计模式。这种模式允许我们将不同的算法封装成独立的策略类,然后根据需要在运行时选择合适的策略。这篇博客将介绍策略模式的概念,并提供一个简单的Java代码示例来说明如何使用策略模式。

策略模式简介

策略模式是一种行为型设计模式,它允许我们定义一系列算法,将每个算法封装成一个独立的策略类,然后在运行时选择使用哪个策略。这种模式有助于将算法的实现与客户端代码分离,使代码更加灵活、可维护和可扩展。

策略模式包括以下主要角色:

  1. 环境(Context):维护一个对策略对象的引用,并在需要时调用所选策略的方法。
  2. 策略(Strategy):定义一组算法接口,具体策略类实现这个接口以提供不同的算法实现。
  3. 具体策略(Concrete Strategy):实现策略接口的具体算法类。

Java代码示例

假设我们正在开发一个电商网站,需要计算购物车中商品的总价格,但不同类型的商品可能有不同的折扣策略。我们可以使用策略模式来实现这个功能。

首先,让我们创建策略接口 PricingStrategy

java 复制代码
// 策略接口
public interface PricingStrategy {
    double calculatePrice(double originalPrice);
}

然后,我们可以创建不同的具体策略类,每个类代表一个不同的折扣策略:

java 复制代码
// 具体策略类:无折扣策略
public class NoDiscountStrategy implements PricingStrategy {
    @Override
    public double calculatePrice(double originalPrice) {
        return originalPrice;
    }
}

// 具体策略类:百分之二十折扣策略
public class TwentyPercentDiscountStrategy implements PricingStrategy {
    @Override
    public double calculatePrice(double originalPrice) {
        return originalPrice * 0.8; // 80% 的价格
    }
}

// 具体策略类:固定折扣策略
public class FixedDiscountStrategy implements PricingStrategy {
    private double discountAmount;

    public FixedDiscountStrategy(double discountAmount) {
        this.discountAmount = discountAmount;
    }

    @Override
    public double calculatePrice(double originalPrice) {
        return originalPrice - discountAmount;
    }
}

接下来,我们创建环境类 ShoppingCart,它维护一个对当前选定策略的引用,并在需要时调用该策略:

java 复制代码
public class ShoppingCart {
    private PricingStrategy pricingStrategy;

    public void setPricingStrategy(PricingStrategy pricingStrategy) {
        this.pricingStrategy = pricingStrategy;
    }

    public double checkout(double originalPrice) {
        // 使用选定的策略来计算最终价格
        double finalPrice = pricingStrategy.calculatePrice(originalPrice);
        return finalPrice;
    }
}

最后,我们可以在客户端代码中使用策略模式:

java 复制代码
public class Main {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();
        double originalPrice = 100.0;

        // 选择不同的折扣策略
        cart.setPricingStrategy(new NoDiscountStrategy());
        double finalPrice1 = cart.checkout(originalPrice);

        cart.setPricingStrategy(new TwentyPercentDiscountStrategy());
        double finalPrice2 = cart.checkout(originalPrice);

        cart.setPricingStrategy(new FixedDiscountStrategy(10.0));
        double finalPrice3 = cart.checkout(originalPrice);

        System.out.println("无折扣策略价格:" + finalPrice1);
        System.out.println("百分之二十折扣策略价格:" + finalPrice2);
        System.out.println("固定折扣策略价格:" + finalPrice3);
    }
}

这个示例演示了策略模式的使用,客户端代码可以根据需要在运行时选择不同的策略来计算最终价格。策略模式使代码更加灵活,易于维护和扩展,因为我们可以轻松添加新的折扣策略而不影响现有代码。

策略模式使用场景

策略模式在以下情况下特别有用,可以帮助组织代码并提高可维护性:

  1. 多种算法或行为选择:当一个类有多种算法或行为可以选择,并且需要在运行时动态切换它们时,策略模式非常有用。这样可以避免使用大量的条件语句来判断应该执行哪个算法。

  2. 避免条件语句的滥用:策略模式有助于减少大量的条件语句,提高代码的可读性和可维护性。替代条件语句通常是一个更好的选择。

  3. 相似的类仅在算法或行为上有差异:如果你有多个类,它们的方法实现基本相同,但在某些算法或行为上有差异,策略模式可以将共享的代码放在一个类中,并将不同的算法封装到独立的策略类中。

  4. 动态配置和扩展:策略模式允许在不修改现有代码的情况下添加新的策略,从而实现动态的配置和扩展。这对于插件系统和可扩展的应用程序非常有用。

  5. 算法族:当你有一个算法族,其中每个算法都可以看作是一个变体时,策略模式非常适用。例如,排序算法就是一个典型的算法族,其中不同的排序算法可以作为不同的策略。

  6. 测试和单元测试:使用策略模式可以更容易地进行单元测试,因为可以为每个策略编写独立的测试用例,而不需要涉及复杂的状态管理。

  7. 减少代码重复:策略模式有助于减少重复的代码。相同的策略可以在不同的上下文中共享和重用。

总之,策略模式是一种有助于提高代码的灵活性、可维护性和可扩展性的设计模式,特别适用于需要动态选择算法或行为的情况。它有助于将不同的策略封装成独立的类,降低了耦合度,使代码更易于理解和维护。

策略模式优缺点

策略模式是一种有用的设计模式,但它也有其优点和缺点,下面分别介绍:

优点:

  1. 可扩展性:策略模式允许在不修改现有代码的情况下添加新的策略。这使得系统更具可扩展性,可以轻松地引入新的算法或行为。

  2. 灵活性:策略模式提供了一种动态切换算法或行为的方式,使得在运行时可以选择不同的策略。这种灵活性对于根据不同条件应用不同的策略非常有用。

  3. 可维护性:将每个策略封装到独立的类中,有助于代码的组织和维护。策略模式有助于减少条件语句的使用,提高代码的可读性和可维护性。

  4. 单一职责原则:策略模式有助于遵循单一职责原则,因为每个策略类都只负责一个特定的算法或行为。

  5. 测试容易:由于每个策略都是独立的,因此可以更容易地编写单元测试来验证每个策略的正确性。

缺点:

  1. 类数量增加:使用策略模式会引入许多策略类,这可能会导致类的数量增加,使代码变得更加复杂。在某些情况下,这可能会导致类爆炸问题。

  2. 客户端责任:客户端需要知道各种策略的存在并选择合适的策略。这可能会增加客户端的复杂性,特别是在策略较多时。

  3. 策略切换开销:在某些情况下,动态切换策略可能会引入一些运行时开销,因为需要进行策略选择和切换。这可能会影响性能。

  4. 不适用于所有情况:策略模式并不是适用于所有问题的解决方案。它最适用于需要在运行时选择不同算法或行为的情况,而对于某些简单的情况,条件语句可能更为合适。

总的来说,策略模式是一种有助于提高代码灵活性和可维护性的设计模式,但它也可能引入一些复杂性,并且不适用于所有情况。在使用策略模式时,需要权衡其优点和缺点,确保在特定情境下使用它是合适的选择。

相关推荐
张小姐的猫13 小时前
【Linux】网络编程 —— HTTP协议(上)
linux·运维·服务器·网络·http·单例模式·策略模式
杨充15 小时前
10.可测试性实战设计
设计模式·开源·代码规范
杨充16 小时前
9.重构十二式的实战
设计模式·开源·代码规范
杨充16 小时前
6.设计原则的全景图
设计模式·开源·全栈
杨充16 小时前
2.面向对象的特性
设计模式
杨充16 小时前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充16 小时前
8.反模式与坏味道
设计模式·开源·代码规范
杨充16 小时前
3.接口vs抽象类比较
设计模式
咖啡八杯19 小时前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法