-
Notifications
You must be signed in to change notification settings - Fork 3
/
visitor2.ts
132 lines (104 loc) · 3.52 KB
/
visitor2.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import { IRunner } from '../../runner';
var formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 2,
});
interface IVisitor2 {
visitClerk(item: Clerk2);
visitEmployee(item: Employee2);
}
class IncomeVisitor2 implements IVisitor2 {
visitClerk(item: Clerk2) {
item.income *= 1.1;
}
visitEmployee(item: Employee2) {
item.income *= 1.3;
}
}
class VacationVisitor2 implements IVisitor2 {
public visitClerk(item: Clerk2) {
item.vactionDays += 1;
}
public visitEmployee(item: Employee2) {
item.vactionDays += 3;
}
}
class LogVisitor2 implements IVisitor2 {
private _visitedItems: (Clerk2 | Employee2)[] = [];
public visitClerk(item: Clerk2) {
this.visit(item);
}
public visitEmployee(item: Employee2) {
this.visit(item);
}
private visit(item: Clerk2 | Employee2) {
const loggedItems = this._visitedItems.filter(i => i.name === item.name);
if (loggedItems.length) {
this.log(item, loggedItems[0]);
} else {
this._visitedItems.push(Object.assign({},item));
this.log(item);
}
}
private log(item: Clerk2 | Employee2, previous = null): void {
if (!previous) {
console.log(`${(<any>item.constructor).name} - ${item.name}'s income: ${formatter.format(item.income)}, vacation days: ${item.vactionDays}`);
} else {
let incomeDelta = '';
if (item.income !== previous.income) {
incomeDelta = `${formatter.format(item.income)} <span style="color: green">(+${formatter.format(item.income - previous.income)})</span>`;
}
let vacationDelta = '';
if (item.vactionDays !== previous.vactionDays) {
vacationDelta = `${item.vactionDays} <span style="color: green">(+${item.vactionDays - previous.vactionDays})</span>`;
}
console.log(`${(<any>item.constructor).name} - ${item.name}'s new income: ${item.income} ${incomeDelta}, vacation days: ${item.vactionDays} ${vacationDelta}`);
}
}
}
interface IVisitableItem2 {
accept(v: IVisitor2);
}
class Employee2 implements IVisitableItem2 {
constructor(
public name: string,
public income: number = 10000,
public vactionDays: number = 30,
) { }
public accept(v: IVisitor2) {
v.visitEmployee(this);
}
}
class Clerk2 extends Employee2 {
constructor(name: string) {
super(name);
}
public accept(v: IVisitor2) {
v.visitClerk(this);
}
}
class Employees2 implements IVisitableItem2 {
constructor(
public employees: Employee2[] = []
) { }
public accept(v: IVisitor2) {
this.employees.forEach(e => e.accept(v));
}
}
export class VisitorPattern2 implements IRunner {
public run(): void {
const list = new Employees2([new Clerk2('Alan'), new Employee2('Tim'), new Employee2('Zoe')]);
const logVisitor = new LogVisitor2();
console.log('<span style="color: orange">Accept LogVisitor2</span>');
list.accept(logVisitor);
console.log('<br/>');
console.log('<span style="color: orange">Accept IncomeVisitor2</span>');
list.accept(new IncomeVisitor2());
list.accept(logVisitor);
console.log('<br/>');
console.log('<span style="color: orange">Accept VacationVisitor2</span>');
list.accept(new VacationVisitor2());
list.accept(logVisitor);
}
}