■ 정의
[GOF]
- 공유를 통한 많은 수의 소립 객체들을 효과적으로 지원
[ 실용주의 디자인패턴 ]
- 메모리 사용량을 줄이기 위해 외부 상태(상태정보 저장, 계산)를 사용하거나
공유(객체의 복사본 대신 단일 객체에 대한 다중 참조를 이용)한다.
- 무엇을 하느냐에 의해 정의, 즉 메소드에 의해 정의됨
▶ 즉 공유하는 객체를 이용하되 상태 정보를 외부 객체가 따로 관리
■ 사용 예
- game of life를 단순하게 구현할때 '셀'이 살아있는가?는 주변 상태를 참조를 지니고 있어야된다. 1024*1024를 표현하려해도 40mb가 필요함
flywieght를 사용하면 동일한 상태를 지닌 객체가 단 하나의 객체를 통해 표현
■ 장/단점
- 장점 : flyweight를 사용하지 않으면 객체지향적으로 구현하기가 힘듬
- 장점 : flyweight 풀을 이용하면 자바의 == 연산자로 객체의동일성 여부를 결정 할 수 있다.
- 단점 : 외부상태가 계산되는 값이라면(매번 데이터베이스에 접근) 하면 접근이 느릴 수 있다.
- 단점 : 코드가 복잡해짐, 유지보수를 어렵게하고 코드가 커질 수 있음
■ 코드 예제
쉬운 예>
ElementStyle e = new ElementStyle;
e.setMargin(ElementStyleFactory.createMargin(10,10,20,10));
-> 객체는 공유하되 외부 객체가 따로 관리 되도록
게임프로그래밍 패턴예제(js로 구현)>
[origin]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>flyweight origin</title>
</head>
<body>
경량패턴??<br>
어떤 객체의 수가 너무 많아 좀 가볍게 만들고 싶을때 사용<br>
고유상태와 외부상태로 나눔<br>
<br>
예제 : 지형 만들기<br>
타일(고유상태)과 각 타일들이 갖고 있는 정보(외부상태)<br>
<script>
function Terrain(kind){
return {
"TERRAIN_CLASS" : "TERRAIN_CLASS",
"TERRAIN_HILL" : "TERRAIN_HILL",
"TERRAIN_RIVER" : "TERRAIN_RIVER" }[kind];
}
function World(){
this.tiles = {};
}
World.prototype.getMovementCost = function(x,y){
return {
"TERRAIN_CLASS" : 1,
"TERRAIN_HILL" : 2,
"TERRAIN_RIVER" : 3 }[this.tiles[x][y]];
};
World.prototype.getIsWater = function(x,y){
return {
"TERRAIN_CLASS" : false,
"TERRAIN_HILL" : false,
"TERRAIN_RIVER" : true }[this.tiles[x][y]];
};
World.prototype.setTile = function(x,y, value){
this.tiles = this.tiles||{};
this.tiles[x] = this.tiles[x]||{};
this.tiles[x][y] = this.tiles[x][y]||"";
this.tiles[x][y] = value;
};
function Main(){
var world = new World;
var terrain_class = Terrain("TERRAIN_CLASS");
var terrain_hill = Terrain("TERRAIN_HILL");
var terrain_river = Terrain("TERRAIN_RIVER");
world.setTile(1,1,terrain_class) ;
world.setTile(1,2,terrain_hill) ;
world.setTile(1,3,terrain_river) ;
console.log(world.getIsWater(1,3));
console.log(world.getMovementCost(1,2));
}
window.onload = function(){
Main();
}
</script>
</body>
</html>
[fly weight]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>flyweight </title>
</head>
<body>
경량패턴??<br>
어떤 객체의 수가 너무 많아 좀 가볍게 만들고 싶을때 사용<br>
고유상태와 외부상태로 나눔<br>
<br>
예제 : 지형 만들기<br>
타일(고유상태)과 각 타일들이 갖고 있는 정보(외부상태)<br>
<script>
function Terrain(movementCost, isWater, texture){
var movementCost_;
var isWater_;
var texture_;
function _Terrain(){
this.movementCost_ = movementCost;
this.isWater_ = isWater;
this.texture_ = texture;
}
_Terrain.prototype.getMovementCost = function(){
return this.movementCost_;
};
_Terrain.prototype.isWater = function(){
return this.isWater_;
};
_Terrain.prototype.getTexture = function(){
return this.texture_;
};
if(!(this instanceof _Terrain )){
return new _Terrain();
}
}
var CONST_GLASS_TEXTURE = "GLASS_TEXTURE";
var CONST_HILL_TEXTURE = "HILL_TEXTURE";
var CONST_RIVER_TEXTURE = "RIVER_TEXTURE";
var CONST_WIDTH = 10;
var CONST_HEIGHT = 12;
function World(){
var tiles = {};
function _World(){
this.glassTerrain_ = [1,false,CONST_GLASS_TEXTURE];
this.hillTerrain_ = [2,false,CONST_HILL_TEXTURE];
this.riverTerrain_ = [3,true,CONST_RIVER_TEXTURE];
this.tiles = tiles;
}
_World.prototype.setTile = function(x,y, value){
this.tiles = this.tiles||{};
this.tiles[x] = this.tiles[x]||{};
this.tiles[x][y] = this.tiles[x][y]||"";
this.tiles[x][y] = value;
};
_World.prototype.getTile = function(x,y){
return Terrain.apply(this, this.tiles[x][y]);
};
_World.prototype.generateTerrain = function(){
for(var x=0; x < CONST_WIDTH; x++) {
for(var y=0; y < CONST_HEIGHT; y++){
if(x % 2 == 0){
this.setTile.apply(this, [x,y,this.glassTerrain_]);
}else{
this.setTile.apply(this, [x,y,this.hillTerrain_]);
}
if(y % 3 == 1){
this.setTile.apply(this, [x,y,this.riverTerrain_]);
}
}
}
};
if(!(this instanceof _World )){
return new _World();
}
}
function Main(){
var world = World();
world.generateTerrain();
console.dir(world.getTile(1,1).getMovementCost());
}
window.onload = function(){
Main();
}
</script>
</body>
</html>