策略模式如何改变应用运行时行为而模板模式却不能?为何二者可运行时选择却有动静行为之分?
Great questions—these are exactly the kind of nuanced pattern distinctions that trip up even experienced devs if you don’t dig into how they’re implemented. Let’s break them down one by one.
The core difference boils down to composition vs. inheritance, and how each pattern locks in behavior:
Strategy uses composition: Every variant of behavior is wrapped in its own standalone "strategy" class that implements a common interface. The main "context" class holds a reference to a strategy object—and here’s the key: you can swap that reference out at any point while the program is running.
For example, think of a music player: you could switch between a "NormalPlaybackStrategy" and a "ShufflePlaybackStrategy" mid-playlist, without restarting the player or creating a new instance. The behavior changes dynamically, during runtime.Template Method uses inheritance: The parent class defines a fixed "skeleton" of an algorithm (like "boil water → add ingredient → pour into cup"), and subclasses override specific steps. Once you instantiate a subclass (say,
CoffeeMakerinstead ofTeaMaker), that object’s behavior is baked in. You can’t reconfigure it to act like the other subclass without discarding the original object and creating a new one. The algorithm’s steps are fixed at instantiation, not dynamic during runtime.
The confusion here comes from mixing up "choosing a variant" with "modifying behavior after instantiation":
Strategy lets you modify behavior during an object’s lifetime: Choosing a strategy isn’t just about picking one at startup. You can update the context’s strategy reference while the program is actively running. For example, a game character could switch from a "DefensiveStrategy" to an "OffensiveStrategy" mid-battle, without creating a new character object. The behavior changes in-place, on the fly.
Template Method’s behavior is static after instantiation: "Choosing" a Template Method variant means creating an instance of a specific subclass. Once that object exists, its behavior can’t change—you can’t rewire a
CoffeeMakerto suddenly add tea leaves instead of coffee grounds. The "choice" happens at object creation (which can be at runtime), but the object’s behavior is fixed for its entire lifetime. It’s "static" in the sense that the object’s algorithm doesn’t evolve after it’s created.
Quick Code Examples to Drive This Home
Strategy Pattern (Runtime Switching)
class PaymentStrategy: def pay(self, amount): pass class AlipayStrategy(PaymentStrategy): def pay(self, amount): print(f"Paid ${amount} via Alipay") class WeChatPayStrategy(PaymentStrategy): def pay(self, amount): print(f"Paid ${amount} via WeChat Pay") class PaymentProcessor: def __init__(self, strategy): self.strategy = strategy def switch_strategy(self, new_strategy): self.strategy = new_strategy # Runtime swap def process_payment(self, amount): self.strategy.pay(amount) # Usage processor = PaymentProcessor(AlipayStrategy()) processor.process_payment(100) # Paid $100 via Alipay processor.switch_strategy(WeChatPayStrategy()) processor.process_payment(50) # Paid $50 via WeChat Pay (switched mid-session)
Template Method (Static Behavior Post-Instantiation)
class BeverageMaker: def make_beverage(self): self.boil_water() self.add_ingredient() self.pour_in_cup() def boil_water(self): print("Boiling water...") def pour_in_cup(self): print("Pouring into cup...") # To be overridden by subclasses def add_ingredient(self): pass class CoffeeMaker(BeverageMaker): def add_ingredient(self): print("Adding coffee grounds") class TeaMaker(BeverageMaker): def add_ingredient(self): print("Adding tea leaves") # Usage coffee_maker = CoffeeMaker() coffee_maker.make_beverage() # Makes coffee—can't make tea without a new instance # No way to make coffee_maker add tea leaves after it's created!
内容的提问来源于stack exchange,提问作者soodankit

