Lab
Composite
// 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();
}