Lab
Chain of responsibility
// A lost-property claim, and what one desk decides about it.
type Claim = { caseId: string; item: string; seenAt: string };
type Decision = 'pass' | 'claimed' | 'blocked';
type Desk = { name: string; handle: (claim: Claim) => Decision };
type Outcome = { status: string; desk: string; checked: string[] };
// Security keeps what it confiscated at screening: those claims stop here.
const security: Desk = {
name: 'security',
handle: (claim) => (claim.seenAt === 'screening' ? 'blocked' : 'pass'),
};
const terminal: Desk = {
name: 'terminal',
handle: (claim) => (claim.seenAt === 'terminal' ? 'claimed' : 'pass'),
};
const airline: Desk = {
name: 'airline',
handle: (claim) => (claim.seenAt === 'airline' ? 'claimed' : 'pass'),
};
// The central store takes whatever reaches it.
const central: Desk = { name: 'central', handle: () => 'claimed' };
// Offer the claim to each desk in order; the first claim or block ends it.
function routeClaim(claim: Claim, desks: Desk[]): Outcome {
const checked: string[] = [];
for (const desk of desks) {
const decision = desk.handle(claim);
checked.push(desk.name);
if (decision !== 'pass') {
return { status: decision, desk: desk.name, checked };
}
}
return { status: 'unhandled', desk: 'nobody', checked };
}
// Route one claim and print where it ended up.
function report(claim: Claim, desks: Desk[]) {
const outcome = routeClaim(claim, desks);
const where = `${outcome.status} by ${outcome.desk}`;
const path = outcome.checked.join(' > ');
console.log(`${claim.caseId} ${claim.item}: ${where}; checked ${path}`);
}
// The intake owner chooses which desks are open, and their order.
const day = [security, terminal, airline, central];
const night = [security, terminal, airline]; // the central store is closed
const pouch = { caseId: 'LP-202', item: 'camera pouch', seenAt: 'airline' };
const powerBank = { caseId: 'LP-203', item: 'power bank', seenAt: 'screening' };
const umbrella = { caseId: 'LP-205', item: 'umbrella', seenAt: 'gate 12' };
report(pouch, day);
report(powerBank, day);
report(umbrella, night);
TODO
Visual to come