| Lesson 5 | Why use design patterns? |
| Objective | Understand how design patterns improve design quality, speed delivery, and make systems easier to change. |
Design patterns are named, proven arrangements of roles and collaborations that solve recurring design problems. They accelerate communication (“use Strategy here”), reduce coupling, and create clear seams for testing and change. They are not silver bullets-but when applied deliberately, they shorten time-to-first-feature and lower long-term maintenance cost.
| Phase | How Patterns Help | Typical Deliverables |
|---|---|---|
| Analysis | Turn vague “variability points” into candidate roles (Policy, Strategy, Observer, Adapter). | Context diagrams, responsibility notes, candidate role list. |
| Design | Choose patterns to isolate construction, behavior changes, and collaboration. | Class/sequence sketches, interface contracts, trade-off notes. |
| Implementation | Faster coding using known layouts (factories, decorators, mediators). | Interfaces + small classes with clear responsibilities. |
| Testing | Mock collaborators behind interfaces; test policies in isolation. | Unit tests per role; contract tests for shared interfaces. |
| Documentation | Concise explanations using pattern names instead of pages of prose. | “We use Observer for events; Strategy for pricing” in README/design notes. |
Java - Strategy to vary business rules without branching:
public interface PriceRule { BigDecimal apply(BigDecimal base); }
public final class HolidayDiscount implements PriceRule {
public BigDecimal apply(BigDecimal base) { return base.multiply(new BigDecimal("0.90")); }
}
public final class NoDiscount implements PriceRule {
public BigDecimal apply(BigDecimal base) { return base; }
}
public final class CheckoutService {
private final PriceRule rule; // injected (composition over inheritance)
public CheckoutService(PriceRule rule) { this.rule = rule; }
public BigDecimal total(BigDecimal subtotal) { return rule.apply(subtotal); }
}
// Swap policies at runtime: new CheckoutService(new HolidayDiscount())
Java - Factory Method to defer concrete selection:
abstract class ImageStore {
public final Image load(String id) {
Storage s = open(); // factory method
try { return s.fetch(id); }
finally { s.close(); }
}
protected abstract Storage open();
}
class S3ImageStore extends ImageStore {
protected Storage open() { return new S3Storage(/* config */); }
}