Proxy Design Pattern
Video Lecture
Overview
... To read hidden text, either pause Video Lectures, refer to Book or subscribe to Medium Membership.
Terminology
... To read hidden text, either pause Video Lectures, refer to Book or subscribe to Medium Membership.
Proxy UML Diagram

Source Code
./src/proxy/proxy-concept.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 | // A Proxy Concept Example
interface ISubject {
// An interface implemented by both the Proxy and Real Subject
request(): void
// A method to implement
}
class RealSubject implements ISubject {
// The actual real object that the proxy is representing
enormousData: number[]
constructor() {
// hypothetically enormous amounts of data
this.enormousData = [1, 2, 3]
}
request() {
return this.enormousData
}
}
class ProxySubject implements ISubject {
// In this case the proxy will act as a cache for
// `enormous_data` and only populate the enormous_data when it
// is actually necessary
enormousData: number[]
realSubject: RealSubject
constructor() {
this.enormousData = []
this.realSubject = new RealSubject()
}
request() {
// Using the proxy as a cache, and loading data into it only if
// it is needed
if (this.enormousData.length === 0) {
console.log('pulling data from RealSubject')
this.enormousData = this.realSubject.request()
return this.enormousData
}
console.log('pulling data from Proxy cache')
return this.enormousData
}
}
// The Client
const PROXY_SUBJECT = new ProxySubject()
// Use the Subject. First time it will load the enormous amounts of data
console.log(PROXY_SUBJECT.request())
// Use the Subject again, but this time it retrieves it from the local cache
console.log(PROXY_SUBJECT.request())
|
Output
node ./dist/proxy/proxy-concept.js
pulling data from RealSubject
[ 1, 2, 3 ]
pulling data from Proxy cache
[ 1, 2, 3 ]
Proxy Use Case
... To read hidden text, either pause Video Lectures, refer to Book or subscribe to Medium Membership.
Example UML Diagram

Source Code
./src/proxy/client.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | import Lion from './lion'
const PROTEUS = new Lion()
PROTEUS.tellMeYourForm()
PROTEUS.tellMeTheFuture()
PROTEUS.tellMeYourForm()
PROTEUS.tellMeTheFuture()
PROTEUS.tellMeYourForm()
PROTEUS.tellMeTheFuture()
PROTEUS.tellMeYourForm()
PROTEUS.tellMeTheFuture()
PROTEUS.tellMeYourForm()
PROTEUS.tellMeTheFuture()
PROTEUS.tellMeYourForm()
PROTEUS.tellMeTheFuture()
PROTEUS.tellMeYourForm()
|
./src/proxy/iproteus.ts
| // The Proteus Interface
export default interface IProteus {
// A Greek mythological character that can change to many forms
tellMeTheFuture(): void
// Proteus will change form rather than tell you the future
tellMeYourForm(): void
// The form of Proteus is elusive like the sea
}
|
./src/proxy/lion.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 | import IProteus from './iproteus'
import Leopard from './leopard'
import Serpent from './serpent'
export default class Lion implements IProteus {
// Proteus in the form of a Lion
name = 'Lion'
tellMeTheFuture(): void {
// Proteus will change to something random
if (Math.floor(Math.random() * 2)) {
Object.assign(this, new Serpent())
this.tellMeTheFuture = Serpent.prototype.tellMeTheFuture
this.tellMeYourForm = Serpent.prototype.tellMeYourForm
} else {
Object.assign(this, new Leopard())
this.tellMeTheFuture = Leopard.prototype.tellMeTheFuture
this.tellMeYourForm = Leopard.prototype.tellMeYourForm
}
}
tellMeYourForm(): void {
console.log(`I am the form of ${this.name}`)
}
}
|
./src/proxy/serpent.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 | import IProteus from './iproteus'
import Leopard from './leopard'
import Lion from './lion'
export default class Serpent implements IProteus {
// Proteus in the form of a Serpent
name = 'Serpent'
tellMeTheFuture(): void {
// Proteus will change to something random
if (Math.floor(Math.random() * 2)) {
Object.assign(this, new Leopard())
this.tellMeTheFuture = Leopard.prototype.tellMeTheFuture
this.tellMeYourForm = Leopard.prototype.tellMeYourForm
} else {
Object.assign(this, new Lion())
this.tellMeTheFuture = Lion.prototype.tellMeTheFuture
this.tellMeYourForm = Lion.prototype.tellMeYourForm
}
}
tellMeYourForm(): void {
console.log(`I am the form of ${this.name}`)
}
}
|
./src/proxy/leopard.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 | import IProteus from './iproteus'
import Lion from './lion'
import Serpent from './serpent'
export default class Leopard implements IProteus {
// Proteus in the form of a Leopard
name = 'Leopard'
tellMeTheFuture(): void {
// Proteus will change to something random
if (Math.floor(Math.random() * 2)) {
Object.assign(this, new Lion())
this.tellMeTheFuture = Lion.prototype.tellMeTheFuture
this.tellMeYourForm = Lion.prototype.tellMeYourForm
} else {
Object.assign(this, new Serpent())
this.tellMeTheFuture = Serpent.prototype.tellMeTheFuture
this.tellMeYourForm = Serpent.prototype.tellMeYourForm
}
}
tellMeYourForm(): void {
console.log(`I am the form of ${this.name}`)
}
}
|
Output
node ./dist/proxy/client.js
I am the form of Lion
I am the form of Serpent
I am the form of Lion
I am the form of Serpent
I am the form of Leopard
I am the form of Lion
I am the form of Leopard
Summary
... To read hidden text, either pause Video Lectures, refer to Book or subscribe to Medium Membership.