Week 10 Lesson

Design Patterns Part 2: Adapter, Decorator, Command, Repository, MVC/MVVM

Some patterns help connect systems, extend behavior, and separate application layers.

AdapterDecoratorCommandRepositoryMVCMVVMlayering

Learning Objectives

  • Use Adapter to connect incompatible interfaces.
  • Use Decorator to add behavior around an object.
  • Use Command to represent actions.
  • Use Repository to separate persistence from business logic.
  • Explain MVC and MVVM separation.

Lecture Notes

Adapter is used when one interface does not match what your code expects. Suppose your app expects a PaymentGateway with charge(amount), but a provider library exposes createPaymentIntent(valueInCents). An adapter translates between your stable application interface and the provider’s interface. This protects the rest of the system from provider-specific details.

Decorator adds behavior before or after another object without changing that object’s code. A NotifyingTaskRepository might wrap a normal TaskRepository and publish an event after saving. A CachedCatalogRepository might wrap a database repository and cache results. Decorator is useful when behavior should be layered flexibly.

Command turns an action into an object. This is useful for undo/redo, queues, logging, and menu actions. In a drawing app, DrawLineCommand and MoveShapeCommand can both execute and undo. In a task app, CompleteTaskCommand can represent a user action that can be stored in history.

Repository separates data access from business logic. A service should not need to know whether tasks are stored in memory, localStorage, SQLite, or an API. It asks a repository for tasks. This keeps business rules testable and makes storage easier to replace.

MVC, MVP, and MVVM are architectural presentation patterns. Their shared goal is separation between interface, state, and behavior. MVC separates Model, View, and Controller. MVVM often uses a ViewModel to expose state and commands to the View. The exact pattern matters less than the principle: UI code should not own every business rule.

Worked Example: Repository separates storage

Before
class TaskService {
  createTask(title: string) {
    const tasks = JSON.parse(localStorage.getItem('tasks') || '[]');
    tasks.push({ title, completed: false });
    localStorage.setItem('tasks', JSON.stringify(tasks));
  }
}
After / Better
interface TaskRepository {
  findAll(): Task[];
  save(task: Task): void;
}

class TaskService {
  constructor(private repo: TaskRepository) {}

  createTask(title: string) {
    if (title.trim().length === 0) throw new Error('Title required');
    this.repo.save({ title, completed: false });
  }
}
Design lesson: TaskService owns the business rule. The repository owns storage details.

Lab: Repository and UI Separation

Scenario: A task tracker stores data directly inside button click handlers.

Steps

  1. Move validation into a service.
  2. Create a repository interface.
  3. Create one in-memory repository for tests.
  4. Keep UI handlers focused on user interaction.
  5. Explain how this resembles MVC or MVVM separation.

Deliverables

  • Refactored code
  • Repository interface
  • Short architecture note

Assignment

Build a small app screen using a service and repository. The UI should not directly own business rules.

Discussion Prompts

  • What does Adapter protect you from?
  • When is Repository unnecessary?
  • How much logic should live in the UI?

Week 10 Quiz

Use these as quick checks after the lesson.

Question 1

Adapter is used to:

Question 2

Decorator is useful when:

Question 3

Command represents:

Question 4

Repository separates:

Question 5

MVC/MVVM mainly help separate:

Student Notes

Saved in this browser only.