Free degree-level programming lessons for careful independent study.

Degree Level Programmes · Programming 2 · Lesson 17

Design Patterns in Practice

Use selected design patterns carefully: immutability, factory methods, singleton risks and composition.

Lesson Overview

Use selected design patterns carefully: immutability, factory methods, singleton risks and composition.

Portfolio focus: Make a small value object immutable.

ConceptPatterns
Run fileDesignPatternsInPracticeDemo.java
BaselineUser[name=Ada, role=student]
Evidence3 tasks

Starter: think before typing

Before running this patterns example, find the line where the main idea becomes active. Write a prediction: what must already be true for that line to work, and what should be different after it runs? The checked run ends with `User[name=Ada, role=student]`; predict how the focus line helps produce that evidence.

Learning Objectives

  • Explain why patterns are reusable design ideas.
  • Use immutability for safer values.
  • Apply a simple factory method.
  • Prefer composition when it keeps design flexible.

Learning Outcomes

  • By the end of the lesson, you can explain why patterns are reusable design ideas.
  • By the end of the lesson, you can use immutability for safer values.
  • By the end of the lesson, you can apply a simple factory method.
  • By the end of the lesson, you can prefer composition when it keeps design flexible.

Why this idea exists

Design patterns became popular after programmers noticed recurring solutions to recurring design problems. The important idea is shared vocabulary: a pattern name can summarise a design shape and its trade-offs.

Patterns are not magic templates. They arose from experience with object-oriented systems, where flexibility, object creation, shared state and composition repeatedly caused similar problems.

At degree level, patterns should be used sparingly and explained honestly. A factory can clarify object creation, immutability can reduce state bugs, and composition can avoid brittle inheritance, but unnecessary patterns make simple code harder.

Deep dive

Mechanism in this example

The important mechanism is visible around `User student = User.createStudent("Ada");`. Read it as a concrete move in the program, not as decorative syntax: identify what value, object, branch, call or boundary is being created at that point.

Design pressure

At degree level, patterns should be used sparingly and explained honestly. A factory can clarify object creation, immutability can reduce state bugs, and composition can avoid brittle inheritance, but unnecessary patterns make simple code harder.

Failure mode to watch

For Design Patterns in Practice, deliberately disturb the assumption behind `User student = User.createStudent("Ada");`: use an awkward value, missing input, wrong order of calls or boundary case. The useful question is how that disturbance exposes a weakness in the patterns design.

Extension step

Extend the example by doing this: Write a factory method. The point is to make one small change that forces you to revisit the concept, rather than adding unrelated features.

Portfolio standard

The portfolio note should not repeat the lesson wording. It should show the edited code, the run result, and your own explanation of this evidence: refactor inheritance into composition in a tiny example.

Lesson visual

Photographic pattern catalogue with labelled tiles for immutable value, factory, singleton and composition beside Java class diagrams.
Photographic pattern catalogue with labelled tiles for immutable value, factory, singleton and composition beside Java class diagrams.Download visual

Type this and run it

Create DesignPatternsInPracticeDemo.java, type the program, and run it before changing anything. This section is about reproducing the checked baseline.

public class DesignPatternsInPracticeDemo {
  public static void main(String[] args) {
    User student = User.createStudent("Ada");
    System.out.println(student);
  }
}

record User(String name, String role) {
  static User createStudent(String name) {
    return new User(name, "student");
  }
}

Build and run it with:

javac DesignPatternsInPracticeDemo.java && java DesignPatternsInPracticeDemo

Expected baseline: User[name=Ada, role=student]

Run the code in your browser

Use the editor as an experiment surface. First run the checked version, then make one small change to the part of the program that demonstrates patterns and compare the new behaviour with the reference output.

Line-by-line explanation

Read the code as a sequence of responsibilities. The focus line for this lesson is User student = User.createStudent("Ada");; the surrounding lines prepare it, use its result or make the behaviour observable.

public class DesignPatternsInPracticeDemo {

This names the runnable class for the Design Patterns in Practice example, giving the compiler and JVM one clear unit to build.

public static void main(String[] args) {

This is the program entry point. In Design Patterns in Practice, it keeps the demonstration of patterns in one traceable starting script.

User student = User.createStudent("Ada");

This introduces student as named state for Design Patterns in Practice. Later lines can read, update, pass or print that specific value as evidence.

System.out.println(student);

This prints student as the observable evidence for Design Patterns in Practice. The output lets the learner check whether the patterns idea behaved as predicted.

}

This closes the innermost Design Patterns in Practice block, so the immediately preceding method, branch or loop has finished.

}

This closes the outer Design Patterns in Practice structure, returning the reader to the surrounding class or file.

record User(String name, String role) {

This declares a compact immutable data carrier, useful here because Design Patterns in Practice needs a named value with fields.

static User createStudent(String name) {

This starts createStudent, a named Design Patterns in Practice operation. Its parameters describe what information comes in; its body decides what work is done.

return new User(name, "student");

This sends a Design Patterns in Practice result back to the caller, so the surrounding code can use the answer.

}

This closing brace number 3 completes another layer of the Design Patterns in Practice source structure Java has been checking.

}

This closing brace number 4 completes another layer of the Design Patterns in Practice source structure Java has been checking.

Worked example

From code to explanation

Problem: Use Design Patterns in Practice to complete a small portfolio-quality step: Make a small value object immutable.

Method: Locate the line `User student = User.createStudent("Ada");`, explain the exact role it plays, then decide what you would change to extend the example without changing the whole program.

Reveal worked answer

The checked run should produce `User[name=Ada, role=student]`. A strong answer links the result back to patterns: what was created, selected, stored, called or protected, and why that matters for the portfolio task.

Trace the program

Before: Before the key operation, identify the relevant value, object, branch or resource that the patterns concept depends on.

During: Trace `User student = User.createStudent("Ada");` as the Design Patterns in Practice example executes. Say whether that operation creates data, checks a condition, calls behaviour, stores information or crosses a boundary.

After: Compare the run with the expected evidence: `User[name=Ada, role=student]`.

Change: Now write a factory method, run again, and explain the smallest reason the behaviour changed.

Common misconception

A common mistake in design patterns in practice is treating the example as a finished answer. For patterns, the important question is narrower: which operation carries the idea, what does it make possible, and what would break if you changed it carelessly?

Quick checks

1. In this Design Patterns in Practice example, what is the best reason to focus on `User student = User.createStudent("Ada");`?

2. Which evidence is strongest after you edit and rerun this example?

How to study this lesson

For Design Patterns in Practice, predict how patterns changes the run before you press Run.

Use the first portfolio task as your main edit: Make a small value object immutable.

Use the second task as your variation: Write a factory method.

Finish with evidence, not a diary entry: Refactor inheritance into composition in a tiny example.

Portfolio Practice

  1. Make a small value object immutable.
  2. Write a factory method.
  3. Refactor inheritance into composition in a tiny example.

Final self-check

Can you explain the key operation?

Explain the line identified in the quick check in one or two sentences. Your answer should say what it does before the output User[name=Ada, role=student] appears.

Can you justify the portfolio evidence?

Your evidence should include the original run, one edited run, and a short note explaining how the edit affected patterns.

Study route

Practise patterns by predicting the Java example, typing it, running it in the browser, tracing the result and saving portfolio evidence.

Next, move into Team Workflow and Version Control and carry forward one improvement from this lesson into the next program.