Flyweight
The flyweight pattern
The flyweight pattern is a structural pattern and is used to share large resources when using many objects of similar types.
A simple example could be a word processor, imagine the letter 'e' which would appear many times within a document, and so the objects for each 'e' constructed
would have an
intrinsic
state (invariant) the 'e' glyph and an
extrinsic
state (variant) such as the colour and position in the document.
Another example could be an image on a webpage that is a very large (like a map or
collage), the image could be broken into smaller images, with the smaller images
used many times to dynamically form the larger image.
Ignoring browser caching, we'll utilise the flyweight pattern, to prevent the larger image taking too long to load and stopping the user losing interest and moving on to another webpage.
So lets attempt to emulate this using JavaScript and downloading a large image that's broken-up into smaller images and
then randomly showing the smaller images to form a larger picture.
Now I've made four simple images and I will combine them into a pattern, the HTML and the images are:
<img id='redImage' src='RedShade.png' /> | |
<img id='greenImage' src='GreenShade.png' /> | |
<img id='blueImage' src='BlueShade.png' /> | |
<img id='blackImage' src='BlackShade.png' /> |
The client will be the webpage document,
the FlyweightFactory will be called the ImageFactory the JavaScript being:
var imageFactory = function () {
this.flyweightImages = [];
this.getFlyweight = function (key) {
if (!this.flyweightImages[key]) {
this.flyweightImages[key] = new imageElement(key);
}
return this.flyweightImages[key];
}
}
The ConcreteFlyweights will be instances of imageElement which
use the Javascript cloneNode function, which creates
a copy of a HTML element.this.flyweightImages = [];
this.getFlyweight = function (key) {
if (!this.flyweightImages[key]) {
this.flyweightImages[key] = new imageElement(key);
}
return this.flyweightImages[key];
}
}
var imageElement = function (element) {
this.element = document.getElementById(element);
this.draw = function (location) {
var clonedElement = this.element.cloneNode(true);
clonedElement.style.position = 'absolute';
clonedElement.style.top = location.top;
clonedElement.style.left = location.left;
document.getElementById('flyweightImage').appendChild(clonedElement);
}
}
this.element = document.getElementById(element);
this.draw = function (location) {
var clonedElement = this.element.cloneNode(true);
clonedElement.style.position = 'absolute';
clonedElement.style.top = location.top;
clonedElement.style.left = location.left;
document.getElementById('flyweightImage').appendChild(clonedElement);
}
}
We'll call the method draw(location) with location being the extrinsic state of the imageElement to place an image at particular place on the document.
Summary
The flyweight pattern is a useful pattern for storing large objects that have to be reused and it could be argued that it could be called the 'caching pattern'.