Choose how an object is built
Picture
Configuration chooses flat or per-item delivery. A small factory turns that choice into a usable pricing object, so every caller does not repeat construction branches.
Predict
How is the factory’s responsibility different from the pricing strategy’s?
Walk through the small example
The factory chooses and constructs a collaborator. The strategy computes a fee when used. One can create the other without being the same pattern.
Mental model and complete Python solution
Both concrete policy classes expose fee(count). make_fee_policy validates configuration and returns the corresponding object. Unknown names fail explicitly rather than quietly charging under an unintended rule. The factory lives at the construction boundary; business operations can use the resulting interface without repeatedly reading configuration. This is a simple factory, not a claim to implement every Factory Method or Abstract Factory variation.
What the function promises: Policy kind is flat or per_item, with a nonnegative integer amount. fee requires a nonnegative integer count. Values are minor currency units.
class FlatFee:
def __init__(self, amount):
self.amount = amount
def fee(self, count):
if type(count) is not int or count < 0:
raise ValueError("Invalid count")
return self.amount
class PerItemFee:
def __init__(self, amount):
self.amount = amount
def fee(self, count):
if type(count) is not int or count < 0:
raise ValueError("Invalid count")
return self.amount * count
def make_fee_policy(kind, amount):
if type(amount) is not int or amount < 0:
raise ValueError("Invalid amount")
constructors = {"flat": FlatFee, "per_item": PerItemFee}
if kind not in constructors:
raise ValueError("Unknown fee policy")
return constructors[kind](amount)
assert make_fee_policy("flat", 50).fee(3) == 50
assert make_fee_policy("per_item", 10).fee(3) == 30
try:
make_fee_policy("mystery", 10)
except ValueError:
pass
else:
raise AssertionError("Unknown policy was not rejected")
Work and storage: Expected O(1) dispatch and construction for this fixed registry. A factory does not inherently reduce algorithmic work.
When to recognize it: Callers need a working policy without repeating construction choices everywhere.
Check before applying it: Reject unknown configuration. A factory chooses construction; it does not automatically make every later behavior interchangeable.
Change one rule
Only the amount changes, and all policies calculate amount×count. Do we need separate classes per price?
See what changes
No. Parameterize one policy object. Classes represent meaningful behavioral differences, not every configuration value.
Connect
Swap the rule, not the whole feature: A factory can build a strategy; these patterns answer different questions.
Agree on a small promise: Constructed objects still need the promised interface.