You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

学习策略模式的困惑:策略模式与运行时多态的关系及示例说明

Strategy Pattern & Runtime Polymorphism: Deep Dive into Their Relationship

Great question! This is a common point of confusion when learning design patterns, so let's break it down clearly: the strategy pattern doesn't just relate to runtime polymorphism—it relies on it as its core mechanism. Let's start with quick recaps, then walk through a concrete example to see how they work hand in hand.

First: A Quick Refresher on Each Term

  • Runtime Polymorphism (Dynamic Method Dispatch): This is when your language's runtime decides which implementation of a method to execute at runtime, based on the actual type of the object (not the type of the reference pointing to it). In OOP languages like Java, C#, or Python, this happens when you call an overridden method on a superclass/interface reference that points to a subclass implementation.
  • Strategy Pattern: A behavioral design pattern that lets you define a family of interchangeable algorithms, encapsulate each one, and decouple them from the code that uses them. The goal is to make it easy to swap out algorithms without changing the core logic that relies on them.

The Core Connection: Strategy Pattern is a Structured Use of Runtime Polymorphism

Think of the strategy pattern as a "best practice" way to apply runtime polymorphism to solve a specific problem (algorithm interchangeability). Here's the breakdown of how they fit together:

  1. You define a common interface (or abstract class) that all your strategy algorithms must implement. This creates a contract for the behavior.
  2. The "context" class (the code that uses the algorithm) holds a reference to this interface, not any concrete strategy.
  3. At runtime, you can assign different concrete strategy objects to the context's interface reference. Thanks to runtime polymorphism, the context will automatically use the correct algorithm implementation without needing to know exactly which one it's using.

Concrete Example (Java)

Let's use a simple e-commerce payment processing scenario to make this tangible.

Step 1: Define the Strategy Interface

This is the shared contract for all payment methods:

public interface PaymentStrategy {
    void processPayment(double amount);
}

Step 2: Implement Concrete Strategies

Each payment method is a separate strategy, implementing the interface with its own logic:

public class CreditCardPayment implements PaymentStrategy {
    private String cardLastFour;

    public CreditCardPayment(String fullCardNumber) {
        this.cardLastFour = fullCardNumber.substring(fullCardNumber.length() - 4);
    }

    @Override
    public void processPayment(double amount) {
        System.out.printf("Processed $%.2f payment via Credit Card (****-%s)%n", 
            amount, cardLastFour);
    }
}

public class PayPalPayment implements PaymentStrategy {
    private String userEmail;

    public PayPalPayment(String userEmail) {
        this.userEmail = userEmail;
    }

    @Override
    public void processPayment(double amount) {
        System.out.printf("Processed $%.2f payment via PayPal (%s)%n", 
            amount, userEmail);
    }
}

Step 3: The Context Class

This is the code that uses the strategy. It depends only on the PaymentStrategy interface, not concrete implementations:

public class OrderProcessor {
    private PaymentStrategy paymentMethod;

    // Allow swapping the strategy at runtime
    public void setPaymentMethod(PaymentStrategy paymentMethod) {
        this.paymentMethod = paymentMethod;
    }

    public void completeOrder(double totalAmount) {
        if (paymentMethod == null) {
            throw new IllegalStateException("No payment method selected!");
        }
        System.out.println("Processing order total: $" + totalAmount);
        // Runtime polymorphism kicks in here
        paymentMethod.processPayment(totalAmount);
        System.out.println("Order completed successfully!\n");
    }
}

Step 4: Putting It All Together

Now we can swap payment methods at runtime, and polymorphism handles the rest:

public class Main {
    public static void main(String[] args) {
        OrderProcessor order = new OrderProcessor();

        // Pay with Credit Card
        order.setPaymentMethod(new CreditCardPayment("1234567890123456"));
        order.completeOrder(79.99);

        // Switch to PayPal without modifying OrderProcessor
        order.setPaymentMethod(new PayPalPayment("jane.doe@example.com"));
        order.completeOrder(45.50);
    }
}

What's Polymorphism Doing Here?

When order.completeOrder() calls paymentMethod.processPayment(), the paymentMethod variable is of type PaymentStrategy (the interface). But at runtime, it points to either a CreditCardPayment or PayPalPayment object. The JVM dynamically dispatches the processPayment() call to the correct implementation—that's runtime polymorphism in action.

Key Takeaways

  • Runtime polymorphism is the foundation of the strategy pattern. Without it, you'd have to use clunky conditional logic (like if-else chains) to switch between algorithms, which makes your code harder to maintain and violates the Open/Closed Principle (you'd have to modify the context class every time you add a new strategy).
  • The strategy pattern wraps this polymorphic behavior into a clean, reusable design. It makes your code more flexible—you can add a new payment method (like CryptoPayment) just by implementing the PaymentStrategy interface, no changes needed to OrderProcessor.

内容的提问来源于stack exchange,提问作者Learnee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:43:58