Flyweight

Structural example

#include <iostream>
#include <string>
#include <map>
using namespace std;
 
// The 'Flyweight' abstract class
class Flyweight {
public:
	virtual void Operation(int extrinsicstate) = 0;
};
 
// The 'ConcreteFlyweight' class
class ConcreteFlyweight : public Flyweight {
public:
	virtual void Operation(int extrinsicstate) {
		cout << "ConcreteFlyweight: " << extrinsicstate << endl;
	}
};
 
// The 'UnsharedConcreteFlyweight' class
class UnsharedConcreteFlyweight : public Flyweight {
public:
	virtual void Operation(int extrinsicstate) {
		cout << "UnsharedConcreteFlyweight: " << extrinsicstate << endl;
	}
};
 
// The 'FlyweightFactory' class
class FlyweightFactory {
private:
	map<string, Flyweight*> flyweights;
public:
	// Constructor
	FlyweightFactory() {
		flyweights["X"] = new ConcreteFlyweight;
		flyweights["Y"] = new ConcreteFlyweight;
		flyweights["Z"] = new ConcreteFlyweight;
	}
	// Destructor
	virtual ~FlyweightFactory() {
		map<string, Flyweight*>::iterator it = flyweights.begin();
		while (it != flyweights.end()) {
			delete it++->second;
		}
	}
	Flyweight* GetFlyweight(const string &key) {
		return flyweights[key];
	}
};
 
 
// Entry point into console application
int main() {
	// Arbitrary extrinsic state
	int extrinsicstate = 22;
	// intrinsic: あらかじめ定義された、頻繁に再利用されるオブジェクト
	// extrinsic: intrinsicなオブジェクトを組み合わせたオブジェクト
 
	FlyweightFactory *factory = new FlyweightFactory;
 
	// Work with different flyweight instances
	Flyweight *fx = factory->GetFlyweight("X");
	fx->Operation(--extrinsicstate);
 
	Flyweight *fy = factory->GetFlyweight("Y");
	fx->Operation(--extrinsicstate);
 
	Flyweight *fz = factory->GetFlyweight("Z");
	fz->Operation(--extrinsicstate);
 
	UnsharedConcreteFlyweight *fu
		= new UnsharedConcreteFlyweight;
 
	fu->Operation(--extrinsicstate);
 
	delete fu;
	delete factory;
	return 0;
}
 


Real World example

#include <iostream>
#include <string>
#include <string.h>		// strcpy()
#include <map>
using namespace std;
 
// The 'Flyweight' abstract class
class Character {
protected:
	char symbol;
	int width;
	int height;
	int ascent;
	int descent;
	int pointSize;
public:
	virtual void Display(int pointSize) = 0;
};
 
// A 'ConcreteFlyweight' class
class CharacterA : public Character {
public:
	// Constructor
	CharacterA() {
		symbol = 'A';
		width = 120;
		height = 100;
		ascent = 70;
		descent = 0;
	}
	virtual void Display(int pointSize) {
		this->pointSize = pointSize;
		cout << symbol << " (pointsize " << this->pointSize << ")" << endl;
	}
};
 
// A 'ConcreteFlyweight' class
class CharacterB : public Character {
public:
	// Constructor
	CharacterB() {
		symbol = 'B';
		width = 140;
		height = 100;
		ascent = 72;
		descent = 0;
	}
	virtual void Display(int pointSize) {
		this->pointSize = pointSize;
		cout << symbol << " (pointsize " << this->pointSize << ")" << endl;
	}
};
 
// ... C, D, E, etc
 
// A 'ConcreteFlyweight' class
class CharacterZ : public Character {
public:
	// Constructor
	CharacterZ() {
		symbol = 'Z';
		width = 100;
		height = 100;
		ascent = 68;
		descent = 0;
	}
	virtual void Display(int pointSize) {
		this->pointSize = pointSize;
		cout << symbol << " (pointsize " << this->pointSize << ")" << endl;
	}
};
 
 
// The 'FlyweightFactory' class
class CharacterFactory {
private:
	map<char, Character*> _characters;
public:
	virtual ~CharacterFactory() {
		map<char, Character*>::iterator it = _characters.begin();
		while (it != _characters.end()) {
			delete it++->second;
		}
	}
	Character* GetCharacter(char key) {
		// Uses "lazy initialization"
		Character *character = NULL;
		if (_characters[key]) {
			character = _characters[key];
		} else {
			switch (key) {
				case 'A': character = new CharacterA; break;
				case 'B': character = new CharacterB; break;
				// ...
				case 'Z': character = new CharacterZ; break;
			}
			_characters[key] = character;
		}
		return character;
	}
};
 
// Entry point into console application.
int main() {
	// Build a document with text
	string document = "AAZZBBZB";
	char *chars = new char[document.length()+1];
	strcpy(chars, document.c_str());
 
	CharacterFactory *factory = new CharacterFactory;
 
	// extrinsic state
	int pointSize = 10;
 
	// For each character use a flyweight object
	for (char *c = chars; *c != '\0'; ++c) {
		++pointSize;
		Character *character = factory->GetCharacter(*c);
		character->Display(pointSize);
	}
 
	delete factory;
	delete [] chars;
	return 0;
}
 


参考サイト

デザインパターンを“喩え話”で分かり易く理解する
http://www.netlaputa.ne.jp/~hijk/study/oo/designpattern.html



デザインパターンの骸骨たち
http://www002.upp.so-net.ne.jp/ys_oota/mdp/

デザインパターンの使い方: Flyweight
http://japan.internet.com/developer/20080923/26.html
最終更新:2011年12月18日 23:54