← Composite lesson
Lab

Composite

Sign in to run your code

Read the brief and the starter here. With a free account you can edit it, run the sample, step through it and check your work, and your progress is kept.

// Where one send's messages go: a line per delivery.
class Outbox {
  lines: string[] = [];

  add(to: string, subject: string): void {
    this.lines.push(`${to}: ${subject}`);
  }
}

// What an address and a list have in common.
interface Recipient {
  deliver(subject: string, outbox: Outbox): void;
  count(): number; // how many people a send reaches
}

class Address implements Recipient {
  constructor(readonly email: string) {}
  deliver(subject: string, outbox: Outbox): void {
    outbox.add(this.email, subject);
  }
  count(): number {
    return 1;
  }
}

class MailingList implements Recipient {
  constructor(readonly name: string, readonly members: Recipient[]) {}
  // Written when a list held only addresses: anything else is skipped.
  deliver(subject: string, outbox: Outbox): void {
    for (const member of this.members) {
      if (member instanceof Address) member.deliver(subject, outbox);
    }
  }
  count(): number {
    return this.members.filter((member) => member instanceof Address).length;
  }
}

// The mail server: one send, to an address or a list.
function send(to: Recipient, subject: string): string[] {
  const outbox = new Outbox();
  to.deliver(subject, outbox);
  return outbox.lines;
}

// The confirmation before sending: "This will email N people."
function recipientCount(to: Recipient): number {
  return to.count();
}