Facade Pattern

What is Facade pattern for? According to sourcemaking.com, there are mainly two intentions:

  • Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.
  • Wrap a complicated subsystem with a simpler interface.

Facade in formula.ts

In formula.ts, I’d like to expose all functions directly to end users like this:

1
2
const formula = requre('formula.ts');
formula.ADD(1, 2); // suppose to return 3

Absolutely it’s not a good design to mix ~500 functions in a single lib file. In the offical documentation of Excel, functions are categorized into multiple groups:

  • Compatibility functions
  • Cube functions
  • Database functions
  • Date and time functions
  • Engineering functions
  • Financial functions
  • Information functions
  • Logical functions
  • Lookup and reference functions
  • Math and trigonometry functions
  • Statistical functions
  • Text functions
  • Web function

The first idea came to me is Facade pattern, which encapsulats multiple complex subsystems with a single interface object, this is exactly what I want. Here’s an example written in TypeScript for fomula.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
// fist subsystem DateTime
class DateTime {
TODAY () : string {
return (new Date()).toLocaleString();
}
}
// second subsystem Statistical
class Statistical {
ADD (a: number, b: number): number {
return a + b;
}
}
class Formula {
dateTime: DateTime;
statistical: Statistical;
constructor() {
this.dateTime = new DateTime();
this.statistical = new Statistical();
}
TODAY() : string {
return this.dateTime.TODAY();
}
ADD(a: number, b: number): number {
return this.statistical.ADD(a, b);
}
}
let f = new Formula();
console.log('f.ADD(1, 2) = ', f.ADD(1, 2));
console.log('f.TODAY() = ', f.TODAY());

You can run this script in TypeScript Playground, output is like this:

1
2
f.ADD(1, 2) = 3
f.TODAY() = 5/8/2016, 4:00:33 PM

Mixins in TypeScript

In the above example we duplicated the functions in Formula so as to expose an unified interface, this is inevitable. However it kind of borthers me that I had to repeat the return statement in each of them, as matter of fact they didn’t add much value except calling a corresponding function in its subsystem. TypseScript does support a better way by using Mixins to building up classes from reusable components. Here’s an example:

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
class CanEat {
public eat() {
alert('Munch Munch.');
}
}
class CanSleep {
sleep() {
alert('Zzzzzzz.');
}
}
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
if (name !== 'constructor') {
derivedCtor.prototype[name] = baseCtor.prototype[name];
}
});
});
}
class Being implements CanEat, CanSleep {
eat: () => void;
sleep: () => void;
}
applyMixins (Being, [CanEat, CanSleep]);
var being = new Being();
being.sleep();

Here we go, with applyMixins, you no longer need to repeat those returns, making the final class short and concise.