- Mastering JavaScript Design Patterns
- Simon Timms
- 537字
- 2021-08-05 17:14:58
Implementation
To demonstrate an implementation of the Abstract Factory pattern, the first thing we'll need is an implementation of the King
class. The following code provides that implementation:
var KingJoffery= (function () { function KingJoffery() { } KingJoffery.prototype.makeDecision = function () { … }; KingJoffery.prototype.marry = function () { … }; return KingJoffery; })();
Note
This code does not include the module structure suggested in Chapter 2, Organizing Code. Including the boiler-plate module code in every example is tedious and you are all smart cookies, so you know to put this in modules if you're going to actually use it. The fully modularized code is available in the distributed source code.
This is just a regular concrete class and could really contain any implementation details. Similarly, we'll need an implementation of the HandOfTheKing class that is equally unexciting:
var LordTywin = (function () { function LordTywin() { } LordTywin.prototype.makeDecision = function () { }; return LordTywin; })();
The concrete factory method looks like this:
var LannisterFactory = (function () { function LannisterFactory() { } LannisterFactory.prototype.getKing = function () { return new KingJoffery(); }; LannisterFactory.prototype.getHandOfTheKing = function () { return new LordTywin(); }; return LannisterFactory; })();
The preceding code simply instantiates new instances of each of the required classes and returns them. An alternative implementation for a different ruling family would follow the same general form and might look like the following code:
var TargaryenFactory = (function () { function TargaryenFactory() { } TargaryenFactory.prototype.getKing = function () { return new KingAerys(); }; TargaryenFactory.prototype.getHandOfTheKing = function () { return new LordConnington(); }; return TargaryenFactory; })();
The implementation of the Abstract Factory pattern in JavaScript is much easier than in other languages. However, the penalty for this is that you lose the compiler checks, which force a full implementation of either the factory or the products. As we proceed through the rest of the patterns, you'll notice that this is a common theme. Patterns that have a great deal of plumbing in statically typed languages are far simpler but create a greater risk of runtime failure. Appropriate unit tests or a JavaScript compiler can ameliorate this situation.
To make use of the Abstract Factory pattern, we'll first need a class that requires the use of some ruling family. The following is the code for this class:
var CourtSession = (function () { function CourtSession(abstractFactory) { this.abstractFactory = abstractFactory; this.COMPLAINT_THRESHOLD = 10; } CourtSession.prototype.complaintPresented = function (complaint) { if (complaint.severity < this.COMPLAINT_THRESHOLD) { this.abstractFactory.getHandOfTheKing().makeDecision(); } else this.abstractFactory.getKing().makeDecision(); }; return CourtSession; })();
We can now call the CourtSession
class and inject different functionality depending on which factory we pass in:
var courtSession1 = new CourtSession(new TargaryenFactory()); courtSession1.complaintPresented({ severity: 8 }); courtSession1.complaintPresented({ severity: 12 }); var courtSession2 = new CourtSession(new LannisterFactory()); courtSession2.complaintPresented({ severity: 8 }); courtSession2.complaintPresented({ severity: 12 });
Despite the differences between a static language and JavaScript, this pattern remains applicable and useful in JavaScript applications. Creating a kit of objects, that work together is useful in a number of situations: any time when a group of objects needs to collaborate to provide functionality but may need to be replaced wholesale. It may also be a useful pattern when attempting to ensure that a set of objects be used together without substitutions.