M3 — Interfaces, Polymorphism, and Design Patterns

SENG 365 — Software Engineering

Neil Ernst

University of Victoria

2026-10-01

Module Goals

Design Judgement

By the end of this module, you should be able to:

  • introduce an interface in response to a concrete source of variation;
  • distinguish polymorphism from conditional selection;
  • use a class diagram to expose dependencies and responsibilities;
  • recognize Strategy, Iterator, and dependency injection as related decoupling choices; and
  • explain when an interface would be premature.

Interfaces and Polymorphism

Preparation

Before class: Read Robillard, 3rd ed., Chapter 3.

Entry Decision

List<Card> arrange(List<Card> cards, String order) {
    if (order.equals("rank")) { /* ... */ }
    else if (order.equals("suit")) { /* ... */ }
    else if (order.equals("game-value")) { /* ... */ }
    return cards;
}

Would you add another branch, an enum, or an interface? Name the next change your choice handles well.

The Growing Client

final class HandBuilder {
    List<Card> build(Deck deck, int count, String order) {
        List<Card> hand = new ArrayList<>();
        while (hand.size() < count && !deck.isEmpty()) {
            hand.add(deck.draw());
        }
        return arrange(hand, order);
    }
}

Design pressure: New games draw from standard decks, multiple decks, or fixed card sequences. They also arrange hands differently.

Which design decisions are fused to HandBuilder? (i.e., what will be harder to change in the future? )

Candidate Vocabulary

interface CardSource {
    boolean isEmpty();
    Card draw();
}

interface CardOrder {
    int compare(Card left, Card right);
}

final class HandBuilder {
    HandBuilder(CardSource source, CardOrder order) { /* ... */ }
}

Could a library type such as Comparator<Card> or Iterable<Card> express the requirement more clearly?

Pattern or Ordinary Design?

  • Strategy: an interchangeable family of algorithms is a first-class design decision.
  • Iterator: traversal is exposed without exposing collection representation.
  • Dependency injection: the client receives a collaborator instead of constructing it.
  • Interface segregation: a client depends only on the behaviour it uses.

Pattern names help communicate a recurring force and its consequences. They do not make a design good.

Transfer: Car Comparators

This course example is not from the card-library narrative:

fleet.sort(new ByAcceleration());
fleet.sort((c1, c2) ->
    Double.compare(c1.brakingDistance(), c2.brakingDistance()));

Compare a named class, anonymous class, lambda, and factory method. Which communicates intent best if the comparison is stateful or reused?

Java and Python

Python can rely on “if it can do the operation” at run time :


def draw_one(source: CardSource) -> Card:
    return source.draw()

Java normally makes that expectation explicit in a declared type.

Both approaches can be strongly typed; Java is statically typed, while Python is dynamically typed. The design question remains: what behaviour does the client require?

Exit Note

An interface is justified in HandBuilder because __________.

It would be premature if __________.

Class Diagrams as Design Tools

Preparation

Before class: Review Chapter 3, especially Section 3.3.

Bring your previous class design or a photograph of it.

Entry Decision

What can a class diagram reveal more quickly than this code?

final class Game {
    private final Deck deck = new Deck();
    private final Random random = new Random();
    private final ConsoleView view = new ConsoleView();
}

Name one important fact the diagram cannot establish.

Diagram the Current Design

Draw only what matters for this question:

How difficult is it to test a Game with a fixed card sequence and a different view?

Include:

  • classes or interfaces;
  • dependency direction;
  • multiplicity where it affects the decision; and
  • the members needed to explain the relationship.

Do not transcribe every field and method.

Revise the Design

Propose a second diagram that makes the desired variation explicit.

Label each change with its rationale:

  • separate specification from implementation;
  • inject a dependency;
  • segregate an interface; or
  • retain a concrete dependency because variation is not valuable.

UML as a Design Conversation

  • A class diagram is a static view. Other diagrams examine the runtime system.
  • Include detail that bears on the decision; omit noise.
  • Compare current and proposed structures.
  • Treat notation as a lens.
  • Diagrams should be conversation artifacts.

Exit Note

The diagram exposed the dependency from __________ to __________.

That matters because __________.