flyweight pattern
1. Flyweight
Fly(๊ฐ๋ฒผ์ด) + Weight(๋ฌด๊ฒ)๋ฅผ ๋ปํ๋ฉฐ, ๋ณต์ฑ์ ์ฒด๊ธ์์ ์ ๋๋์๋ค.
๋ชจ๋ ๊ฐ์ฒด๋ฅผ ์ผ์ผํ ์ธ์คํด์คํ ํ์ง์๊ณ ์ฌ์ฌ์ฉํ ์ ์๋ ๊ฐ์ฒด๋ ์ฌ์ฌ์ฉํจ์ผ๋ก์จ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ฐ๋ณ๊ฒ ๋ง๋ ๋ค๋ ์๋ฏธ๋ก์ ์ฐ์ธ๋ค๊ณ ๋ณด๋ฉด ๋๋ค.
โ ๊ฐ๋ณ๊ฒ ๋ง๋ ๋ค!

๊ณต์ ๋ ์์๊ณผ ๊ทธ๋ ์ง ์์ ์์์ ์ฌ์ฉ๋ ์ฐจ์ด
2. Flyweight ํจํด ๊ตฌ์กฐ
![]() |
![]() |
---|
Flyweight : ๊ฒฝ๋ ๊ฐ์ฒด๋ฅผ ๋ฌถ๋ ์ธํฐํ์ด์ค
ConcreteFlyweight : ๊ณต์ ๊ฐ๋ฅํ์ฌ ์ฌ์ฌ์ฉ๋๋ ๊ฐ์ฒด(intrinsic state)
UnsahredConcreteFlyweight: ๊ณต์ ๋ถ๊ฐ๋ฅํ ๊ฐ์ฒด (extrinsic state)
FlyweightFactory : ๊ฒฝ๋ ๊ฐ์ฒด๋ฅผ ๋ง๋๋ ๊ณต์ฅ ์ญํ ๊ณผ ์บ์ ์ญํ ์ ๊ฒธ๋นํ๋ Flyweight ๊ฐ์ฒด ๊ด๋ฆฌ ํด๋์ค
- GetFlyweight() ๋ฉ์๋๋ ํฉํ ๋ฆฌ ๋ฉ์๋ ์ญํ ์ ํ๋ค๊ณ ๋ณด๋ฉด ๋๋ค.๋ง์ผ ๊ฐ์ฒด๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ์กด์ฌํ๋ฉด ๊ทธ๋๋ก ๊ฐ์ ธ์ ๋ฐํํ๊ณ , ์๋ค๋ฉด ์๋ก ์์ฑํด ๋ฐํํ๋ค
Client : ํด๋ผ์ด์ธํธ๋ FlyweightFactory๋ฅผ ํตํด Flyweight ํ์
์ ๊ฐ์ฒด๋ฅผ ์ป์ด ์ฌ์ฉํ๋ค.
3. Flyweight pattern ์์ ์ฃผ์ํ ์
๋ณด๋ค์ํผ ๊ตฌํ ๊ฐ์ฒด์ ์ํ๊ฐ ์ค์ํ๋ค.
intrinsic ์ extrinsic ์ํ
โ intrinsic('๊ณ ์ ํ, ๋ณธ์ง์ ์ธโ)ํ ๊ฐ์ฒด : ์ฅ์๋ ์ํฉ์ ์์กดํ์ง ์๊ธฐ ๋๋ฌธ์ ๊ฐ์ด ๊ณ ์ ๋์ด ๊ณต์ ํ ์ ์๋ ๊ฐ์ฒด
extrinsic('์ธ์ ์ธ, ๋น๋ณธ์ง์ ์ธโ)ํ ๊ฐ์ฒด : ์ฅ์๋ ์ํฉ์ ์์กดํ๊ธฐ ๋๋ฌธ์ ๋งค๋ฒ ๊ฐ์ด ๋ฐ๋์ด ๊ณต์ ํ ์ ์๋ ๊ฐ์ฒด
๊ฐ์ฒด๋ค์ ์ํ๋ฅผ ์ ๋ถ๋ฆฌํด์ ์ ์ฉํด์ผํ๋ค.
a. ํญํ ํผํ๊ธฐ ๊ฒ์ ์์

ํญํ ๊ฐ๊ฐ์ ํ๋์ ๊ฐ์ฒด
- ํญํ ๊ฐ์ฒด๋ค์ ์ผ์ผํ new ๋ฅผ ํตํด ์ธ์คํด์คํํ๋ฉด?
- ๊ฐ์ฒด๋ฅผ ์์ฑ ํ ๋๋ง๋ค ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฐจ์งํ๊ฒ ๋์ด ๊ฒ์์ด ๋ฌด๊ฑฐ์์ง ๊ฒ
- ์ด์ฐจํผ ๋จ์ด์ง๋ ํญํ ๊ฐ์ฒด์ ์๊น์๋ ๋ชจ๋ ๊ฐ๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ๊ณ์ ์์ฑํ๋ ๊ฒ์ ์ค๋ณต์ด๋ค.
- ํญํ์ ํ๋ผ์ด์จ์ดํธ๋ก ์ฒ๋ฆฌํจ์ผ๋ก์จ ํญํ ์ธ์คํด์ค๋ ํ๋๋ง ๋ง๋ค๊ณ ๊ณต์ ํ๋ ๋ฐฉ์์ผ๋ก ํ๋ฉด์ ๋ฟ๋ฆฌ๋ฉด ๋๋ค.
โ ๏ธ ์ฃผ์์ !
ํญํ ์์ ์์ intrinsic ์ํ์ ๋ณด์ extrinsic ์ํ์ ๋ณด๋ฅผ ๋ถ๋ฆฌํด์ ์๊ฐํด๋ณด์.
ํญํ์ด ๊ฐ๊ณ ์๋ ์ ๋ณด ๋ชฉ๋ก์ ๋ค์๊ณผ ๊ฐ๋ค.
- ํญํ ๋ชจ์
- ํญํ ์๊น
- ํญํ x, y ์ขํ ์์น
์ฌ๊ธฐ์ 1๋ฒ 2๋ฒ์ ํญํ์ ๋ณธ์ง์ ์ธ ๊ณ ์ ํ ์ํ๋ฅผ ๋ํ๋ด๊ธฐ ๋๋ฌธ์ ์ฌ๋ฌ๊ณณ์ ๊ณต์ ๊ฐ ๊ฐ๋ฅํ๋ค.
๋ฐ๋ฉด, ์์น๊ฐ์ ์ค์๊ฐ์ผ๋ก ๋ณํํ๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ์บ์ํ์ฌ ๊ณต์ ํ ์๋ ์๋ค.
์ด๋ฅผ flyweight pattern์ ์ ์ฉํด๋ณด์๋ฉด,
ConcreteFlyweight๊ฐ์ฒด์๋ ๊ณ ์ ์ ์ ๋ณด์ธ 1,2๋ฒ์ด ํฌํจ๋๊ฒ ๋ ๊ฒ์ด๊ณ ,
UnsharedConcreteFlyweight๊ฐ์ฒด์๋ ๋น ๊ณ ์ ์ ์ ๋ณด์ธ 3๋ฒ์ด ํฌํจ๋๊ฒ ๋ ๊ฒ์ด๋ค.
๊ทธ๋ฆฌ๊ณ ์ด ๋ ํญํ ๊ฐ์ฒด๋ค์ FlyweightFactory๊ฐ ์์ฑํ๊ณ ๊ด๋ฆฌํ๊ฒ ๋๋ ๊ฒ์ด๋ค.
4. ํน์ง
a. ์ ์ฉ์๊ธฐ
- ์ดํ๋ฆฌ์ผ์ด์ ์ ์ํด ์์ฑ๋๋ ๊ฐ์ฒด์ ์๊ฐ ๋ง์ ์ ์ฅ ๋น์ฉ์ด ๋์์ง ๋
- ์์ฑ๋ ๊ฐ์ฒด๊ฐ ์ค๋๋๋ก ๋ฉ๋ชจ๋ฆฌ์ ์์ฃผํ๋ฉฐ ์ฌ์ฉ๋๋ ํ์๊ฐ ๋ง์๋
- ๊ณตํต์ ์ธ ์ธ์คํด์ค๋ฅผ ๋ง์ด ์์ฑํ๋ ๋ก์ง์ด ํฌํจ๋ ๊ฒฝ์ฐ
- ์๋ฒ ๋๋์ ๊ฐ์ด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ต์ํ์ผ๋ก ์ฌ์ฉํด์ผํ๋ ๊ฒฝ์ฐ์ ํ์ฉ โ ์ ์ด์ ํ๋ฝ๋ ์์์ ์ ์์ฒด๊ฐ ์ ๋ค
b. ์ฅ์
- ์ดํ๋ฆฌ์ผ์ด์ ์์ ์ฌ์ฉํ๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ค์ผ ์ ์๋ค.
- ํ๋ก๊ทธ๋จ ์๋๋ฅผ ๊ฐ์ ํ ์ ์๋ค.
- new๋ก ์ธ์คํด์คํ ํ๋ฉด ๋ฐ์ดํฐ๊ฐ ์์ฑ๋๊ณ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฌ๋๋ ์์ฃผ ์ฝ๊ฐ์ ์๊ฐ์ด ์์๋๋ค.
- ๊ฐ์ฒด๋ฅผ ๊ณต์ ํ๋ฉด ์ธ์คํด์ค๋ฅผ ๊ฐ์ ธ์ค๊ธฐ๋ง ํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ ๋ฉ๋ชจ๋ฆฌ ๋ฟ๋ง ์๋๋ผ ์๋๋ ํฅ์์ํฌ ์ ์๊ฒ ๋๋ ๊ฒ์ด๋ค.
c. ๋จ์
- ์ฝ๋์ ํน์ก์ฑ ์ฆ๊ฐ
5. ๋ง์ธํฌ๋ํํธ์ ๋๋ฌด์ฌ๊ธฐ ์์
๋ง์ธํฌ๋ํํธ์ ์ฒ์ ๊ตฌํํ๊ธฐ ์ํด์ ์งํ(Terrain)์ ๋๋ฌด ๊ฐ์ฒด๋ค์ ์ฌ์ผ๋ ค๊ณ ํ๋ค.

๋๋ฌด์ ์ข ๋ฅ
๋๋ฌด ๊ฐ์ฒด์ ํ์ํ ๋ฐ์ดํฐ๋ ๋ค์๊ณผ ๊ฐ๋ค.
- ๋๋ฌด ์ข ๋ฅ
- ์ค๊ธฐ, ๊ฐ์ง, ์์ ํํ๋ฅผ ๋ํ๋ด๋ ํด๋ฆฌ๊ณค ๋ฉ์ (mesh) โ ํํ ๊ด๋ จ
- ๋๋ฌด ๊ป์ง ํ ์ค์ณ (texture) โ ํํ ๊ด๋ จ
- ์ ์ฌ๊ท ํ ์ค์ณ (texture) โ ํํ ๊ด๋ จ
- ์ฒ์์์ ์์น ๋งค๊ฐ๋ณ์
No Clean Code

์์ ์์์ ๋ค์ด์๋ ๋ด์ฉ์ ๋ชจ๋ ๋๋ฌด๊ฐ ๋์ผํ๋ค.
Memory.java : ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ์ฒดํฌ์ฉ ํด๋์ค
class Memory {
public static long size = 0; // ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋
public static void print() {
System.out.println("์ด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ : " + Memory.size + "MB");
}
}
Tree.java : Tree ๊ฐ์ฒด ํด๋์ค
class Tree {
long objSize = 100; // 100MB
String type; // ๋๋ฌด ์ข
๋ฅ
Object mesh; // ๋ฉ์ฌ
Object texture; // ๋๋ฌด ๊ป์ง + ์์ฌ๊ท ํ
์ค์ณ
// ์์น ๋ณ์
double position_x;
double position_y;
public Tree(String type, Object mesh, Object texture, double position_x, double position_y) {
this.type = type;
this.mesh = mesh;
this.texture = texture;
this.position_x = position_x;
this.position_y = position_y;
// ๋๋ฌด ๊ฐ์ฒด๋ฅผ ์์ฑํ์์ผ๋ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ ํฌ๊ธฐ ์ฆ๊ฐ
Memory.size += this.objSize;
}
}
Terrain.java : ์งํ ํด๋์ค, ๋๋ฌด๋ฅผ ์์ฑํ๋ ํด๋ผ์ด์ธํธ ๊ฐ์ฒด
// Client
class Terrain {
// ์งํ ํ์ผ ํฌ๊ธฐ
static final int CANVAS_SIZE = 10000;
// ๋๋ฌด๋ฅผ ๋ ๋๋ง
public void render(String type, Object mesh, Object texture, double position_x, double position_y) {
// ๋๋ฌด๋ฅผ ์งํ์ ์์ฑ
Tree tree = new Tree(
type, // ๋๋ฌด ์ข
๋ฅ
mesh, // mesh
texture, // texture
Math.random() * CANVAS_SIZE, // position_x
Math.random() * CANVAS_SIZE // position_y
);
System.out.println("x:" + tree.position_x + " y:" + tree.position_y + " ์์น์ " + type + " ๋๋ฌด ์์ฑ ์๋ฃ");
}
}
main
public static void main(String[] args) {
// ์งํ ์์ฑ
Terrain terrain = new Terrain();
// ์งํ์ Oak ๋๋ฌด 5 ๊ทธ๋ฃจ ์์ฑ
for (int i = 0; i < 5; i++) {
terrain.render(
"Oak", // type
new Object(), // mesh
new Object(), // texture
Math.random() * Terrain.CANVAS_SIZE, // position_x
Math.random() * Terrain.CANVAS_SIZE // position_y
);
}
// ์งํ์ Acacia ๋๋ฌด 5 ๊ทธ๋ฃจ ์์ฑ
for (int i = 0; i < 5; i++) {
terrain.render(
"Acacia", // type
new Object(), // mesh
new Object(), // texture
Math.random() * Terrain.CANVAS_SIZE, // position_x
Math.random() * Terrain.CANVAS_SIZE // position_y
);
}
// ์งํ์ Jungle ๋๋ฌด 5 ๊ทธ๋ฃจ ์์ฑ
for (int i = 0; i < 5; i++) {
terrain.render(
"Jungle", // type
new Object(), // mesh
new Object(), // texture
Math.random() * Terrain.CANVAS_SIZE, // position_x
Math.random() * Terrain.CANVAS_SIZE // position_y
);
}
// ์ด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ฅ ์ถ๋ ฅ
Memory.print();
}

๊ฐ ์ธ์ข ๋ฅ์ ๋๋ฌด๋ฅผ 5๊ฐ์ฉ 100mb๋ฅผ ๊ณฑํ๋ฉด ์ด 1500mb ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ฌ์ฉ๋๊ฒ ๋๋ ๊ฒ.
Clean Code โ Flyweight pattern ์ ์ฉ

์ต์ ํ์ ํต์ฌ์ ๋๋ฌด๊ฐ ์๋ฐฑ ๊ทธ๋ฃจ ๋๊ฒ ์๋๋ค ํด๋ ๋๋ถ๋ถ ๋น์ทํ๊ฒ ๋ณด์ธ๋ค๋ ๊ฒ์ด๋ค.
์ฆ, ๋๋ฌด๋ฅผ ์์ฑํ๋๋ฐ ์ฌ์ฉ๋ mesh, texture๋ฅผ ์ฌ์ฌ์ฉํ์ฌ ํํํด๋ ์ด์ฐจํผ ๊ฐ์ ๋๋ฌด์ด๋ ๋ฌธ์ ๊ฐ ์๋ ๊ฒ์ด๋ค.
๋ฐ๋ผ์ ๊ณตํต์ผ๋ก ์ฌ์ฉ๋ ๋ชจ๋ธ ๋ฐ์ดํฐ, ์ค์๊ฐ์ผ๋ก ๋ณํ๋ ์์น ๋งค๊ฐ๋ณ์๋ฅผ ๋ถ๋ฆฌํ์ฌ ๊ฐ์ฒด๋ฅผ ๊ตฌ์ฑํ๋ค.
์ด๋ ๊ฒ ๋๋ฉด ์งํ์์ ๋๋ฌด๋ฅผ ๊ตฌํํ ๋ ๋๋ฌด ๋ชจ๋ธ ์ธ์คํด์ค ํ๋๋ฅผ ๊ณต์ ๋ฐ๊ณ ์์น ๋งค๊ฐ๋ณ์๋ง ๋ค๋ฅด๊ฒ ์ค์ ํด์ฃผ๋ฉด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ ๋ฐ ์ด์ ์ค์ผ ์ ์์ ๊ฒ์ด๋ค. โ ๋๋ฌด๊ฐ ๋ง์ผ๋ฉด ๋ง์ ์๋ก ์ ์ฝ๋๋ค.
- ์ฝ๊ฒ ๋งํด, ์ค์๊ฐ์ผ๋ก ๋ณํ๋ ์์น๊ฐ๋ณด๋ค ๋๋ฌด๋ฅผ ํํํ๋ ๋ฉ์, ์์ฌ๊ท ๋ฑ์ ๊ฐ์ ์ค์๊ฐ์ผ๋ก ๋ณํ ํ์์์ด ์ฌ์ฌ์ฉํด๋ ์๊ด์๋ค๋ ๊ฑฐ๋ค.

1. intrinsic ๊ฐ์ฒด์ extrinsic ๊ฐ์ฒด ๋ถ๋ฆฌํ๊ธฐ
๋งํฌ ๊ฒ์ ๋ด์์ ๋๊ฐ์ ๋ฉ์์ ๋๋ฌด๊ป์ง ํ ์ค์ณ๋ฅผ ์ผ์ผํ ์ฌ๋ฌ๋ฒ ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ฆด ์ด์ ๊ฐ ์๊ธฐ ๋๋ฌธ์ ๊ณต์ ๋๋ ๋๋ฌด ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ๊ธฐ์กด Tree ํด๋์ค์์ ๋ฐ๋ก ๋นผ์ค๋ค.
instrinsic : mesh, texture
extrinsic : position ์ขํ
TreeModel.java : ๋ถ๋ณ๊ฐ์ฒด
// ConcreteFlyweight - ํ๋ผ์ด์จ์ดํธ ๊ฐ์ฒด๋ ๋ถ๋ณ์ฑ์ ๊ฐ์ ธ์ผํ๋ค. ๋ณ๊ฒฝ๋๋ฉด ๋ชจ๋ ๊ฒ์ ์ํฅ์ ์ฃผ๊ธฐ ๋๋ฌธ์ด๋ค.
final class TreeModel { // final ์ ํตํด ๋ถ๋ณ ๊ฐ์ฒด๋ก ๋ง๋ค์ด์ค
// ๋ฉ์, ํ
์ค์ณ ์ด ์ฌ์ด์ฆ
long objSize = 90; // 90MB
String type; // ๋๋ฌด ์ข
๋ฅ
Object mesh; // ๋ฉ์ฌ
Object texture; // ๋๋ฌด ๊ป์ง + ์์ฌ๊ท ํ
์ค์ณ
public TreeModel(String type, Object mesh, Object texture) {
this.type = type;
this.mesh = mesh;
this.texture = texture;
// ๋๋ฌด ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฌํ์ผ๋ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ ํฌ๊ธฐ ์ฆ๊ฐ
Memory.size += this.objSize;
}
}
Tree.java : ๊ฐ๋ณ ๊ฐ์ฒด
// UnsahredConcreteFlyweight
class Tree {
// ์ฃํ๊ฐ๊ณผ ๋๋ฌด ๋ชจ๋ธ ์ฐธ์กฐ ๊ฐ์ฒด ํฌ๊ธฐ๋ฅผ ํฉ์น ์ฌ์ด์ฆ
long objSize = 10; // 10MB
// ์์น ๋ณ์
double position_x;
double position_y;
// ๋๋ฌด ๋ชจ๋ธ
TreeModel model; // ํฉ์ฑ์ ํตํด ๊ด๊ณ ๋งบ์ด์ค
public Tree(TreeModel model, double position_x, double position_y) {
this.model = model;
this.position_x = position_x;
this.position_y = position_y;
// ๋๋ฌด ๊ฐ์ฒด๋ฅผ ์์ฑํ์์ผ๋ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ ํฌ๊ธฐ ์ฆ๊ฐ
Memory.size += this.objSize;
}
}
2. Flyweight ํฉํ ๋ฆฌ ๋ง๋ค๊ธฐ
๋๋ฌด ๋ชจ๋ธ ๊ฐ์ฒด์ Flyweight๋ฅผ ์ ์ฉ ํ์ผ๋ ์ด๋ฅผ ์์ฑ ๋ฐ ๊ด๋ฆฌํ FlyweightFactory ํด๋์ค๋ฅผ ๋ง๋ ๋ค.
โ ํ๋ผ์ด์จ์ดํธ ํฉํ ๋ฆฌ์ ํต์ฌ
- Flyweight Pool : HashMap ์ปฌ๋ ์ ์ ํตํด ํค(key) ์ ๋๋ฌด ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ์ ์ฅํ๋ ์บ์ ์ ์ฅ์ ์ญํ
- getInstance ๋ฉ์๋ : Pool์ ๊ฐ์ ธ์ค๊ณ ์ ํ๋ ๊ฐ์ฒด๊ฐ ์๋์ง ๊ฒ์ฌ๋ฅผ ํ์ฌ ์์ผ๋ฉด ๊ทธ๋๋ก ๋ฐํ, ์์ผ๋ฉด ์๋ก ์์ฑ
// FlyweightFactory
class TreeModelFactory {
// Flyweight Pool - TreeModel ๊ฐ์ฒด๋ค์ Map์ผ๋ก ๋ฑ๋กํ์ฌ ์บ์ฑ
private static final Map<String, TreeModel> cache = new HashMap<>(); // static final ์ด๋ผ Thread-Safe ํจ
// static factory method
public static TreeModel getInstance(String key) {
// ๋ง์ฝ ์บ์ ๋์ด ์๋ค๋ฉด
if(cache.containsKey(key)) {
return cache.get(key); // ๊ทธ๋๋ก ๊ฐ์ ธ์ ๋ฐํ
} else {
// ์บ์ ๋์ด์์ง ์์ผ๋ฉด ๋๋ฌด ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ์๋ก ์์ฑํ๊ณ ๋ฐํ
TreeModel model = new TreeModel(
key,
new Object(),
new Object()
);
System.out.println("-- ๋๋ฌด ๋ชจ๋ธ ๊ฐ์ฒด ์๋ก ์์ฑ ์๋ฃ --");
// ์บ์์ ์ ์ฌ
cache.put(key, model);
return model;
}
}
}
3. Client ์ต์ ํ
๊ธฐ์กด Terrian ํด๋์ค์ render() ๋ฉ์๋๋ ๋จ์ํ๊ฒ ์ฌ์ฉ์๋ก๋ถํฐ ๋งค๊ฐ๋ณ์๋ฅผ ๋ฐ์ ๊ทธ๋๋ก tree๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
๊ทธ๋ฌ๋ ์ง๊ธ ๊ธฐ์กด Tree๊ฐ์ฒด๋ฅผ ๋ฐ๋ก TreeModel๋ก ๋๋๊ณ , TreeModelFactory๊น์ง ์์ฑํ์ผ๋ ์ด๋ฅผ ์ด์ฉํ๋ ํด๋ผ์ด์ธํธ ์ฝ๋๋ฅผ ์ต์ ํ ํด์ฃผ์ด์ผํ๋ค.
โ Flyweight๋ฅผ ์ด์ฉํ ์ต์ ํ ์์
- ๋จผ์ TreeModel์์ ๊ณต์ ๋๊ณ ์๋ ๋๋ฌด ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์จ๋ค. (์บ์์ ์๋ค๋ฉด ์๋ก ์์ฑ)
- ๊ฐ์ ธ์จ ๋๋ฌด ๋ชจ๋ธ๊ณผ ์ขํ๊ฐ์ ์ด์ฉํด ๋๋ฌด ๊ฐ์ฒด๋ฅผ ์๋ก ์์ฑํ๋ค.
๊ณต์ ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์ ์ฌ์ฉํจ์ผ๋ก์จ ์ธ๋ฐ์๋ mesh ๋ฐ texture ๋ญ๋น๋ฅผ ๋ฐฉ์งํ๋ค.
Terrain.java
// Client
class Terrain {
// ์งํ ํ์ผ ํฌ๊ธฐ
static final int CANVAS_SIZE = 10000;
// ๋๋ฌด๋ฅผ ๋ ๋๋ง
public void render(String type, double position_x, double position_y) {
// 1. ์บ์ ๋์ด ์๋ ๋๋ฌด ๋ชจ๋ธ ๊ฐ์ฒด ๊ฐ์ ธ์ค๊ธฐ
TreeModel model = TreeModelFactory.getInstance(type);
// 2. ์ฌ์ฌ์ฉํ ๋๋ฌด ๋ชจ๋ธ ๊ฐ์ฒด์ ๋ณํํ๋ ์์ฑ์ธ ์ขํ๊ฐ์ผ๋ก ๋๋ฌด ์์ฑ
Tree tree = new Tree(model, position_x, position_y);
System.out.println("x:" + tree.position_x + " y:" + tree.position_y + " ์์น์ " + type + " ๋๋ฌด ์์ฑ ์๋ฃ");
}
}
main
public static void main(String[] args) {
// ์งํ ์์ฑ
Terrain terrain = new Terrain();
// ์งํ์ Oak ๋๋ฌด 5 ๊ทธ๋ฃจ ์์ฑ
for (int i = 0; i < 5; i++) {
terrain.render(
"Oak", // type
Math.random() * Terrain.CANVAS_SIZE, // position_x
Math.random() * Terrain.CANVAS_SIZE // position_y
);
}
// ์งํ์ Acacia ๋๋ฌด 5 ๊ทธ๋ฃจ ์์ฑ
for (int i = 0; i < 5; i++) {
terrain.render(
"Acacia", // type
Math.random() * Terrain.CANVAS_SIZE, // position_x
Math.random() * Terrain.CANVAS_SIZE // position_y
);
}
// ์งํ์ Jungle ๋๋ฌด 5 ๊ทธ๋ฃจ ์์ฑ
for (int i = 0; i < 5; i++) {
terrain.render(
"Jungle", // type
Math.random() * Terrain.CANVAS_SIZE, // position_x
Math.random() * Terrain.CANVAS_SIZE // position_y
);
}
// ์ด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ฅ ์ถ๋ ฅ
Memory.print();
}

ํจํด ์ ์ฉ ์ ์๋ 1500mb ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ๋ค์ด๊ฐ์ผ๋, ํจํด ์ ์ฉ ํ์๋ 420mb๋ก ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ํ ์ค์ด๋ค์๋ค.
์ ์๋ ๊ณ์ ๋๋ฌด๋ฅผ ์์ฑํ๋ ๋ฐ๋ฉด์, ๋๋ฌด ๋ชจ๋ธ์ ๋ฐ๋ก ํ๋ผ์ด์จ์ดํธ๋ก ๋ถ๋ฆฌํจ์ผ๋ก์จ ์ค๋ณต๋ ๊ฐ๋ค์ ๊ณต์ ์์ผ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๊ผ๋ค.
์ด์ฒ๋ผ ๊ณต์ ํ ์ ์๋ intrinsic ์ํ์ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฆฌํ์ฌ ์บ์ฑํจ์ผ๋ก์จ ํ๋ก๊ทธ๋จ์ ์ต์ ํํ๋ ๊ฒ์ด ์ค์ํ๋ค.
์ฃผ์์ฌํญ - GC
์ฐ๋ฆฌ๊ฐ ๊ตฌํํ ์์ ์์๋ TreeModelFactory์์ HashMap์ ์ด์ฉํด TreeModel์ ์ธ์คํด์ค๋ฅผ ์บ์ฑํ์ฌ ๊ด๋ฆฌํ๋ค.
์ด์ฒ๋ผ โ์ธ์คํด์ค๋ฅผ ๊ด๋ฆฌโํ๋ ๊ธฐ๋ฅ์ ์๋ฐ ํ๋ก๊ทธ๋๋ฐ์์ ๊ตฌํํ์ฌ ์ฌ์ฉํ ๋์๋ ๋ฐ๋์!! โ๊ด๋ฆฌ๋๊ณ ์๋ ์ธ์คํด์ค๋ GC(Garbage Collection) ์ฒ๋ฆฌ๋์ง ์๋๋คโ๋ ์ ์ ์ฃผ์ํด์ผํ๋ค.
๊ทธ๋ฐ๋ฐ ์ด์ฐ๋ณด๋ฉด ๋น์ฐํ ์ด์น์ด๋ค. ์ธ์คํด์ค๋ฅผ ๊ด๋ฆฌํ๋ค๋ ๊ฒ ์์ฒด๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ๋๊ณ ๋ด๊ฐ ๊ณต์ ํ ๊ฒ์ด๋ผ๊ณ ํด๋จ๋๋ฐ ์ด๊ฑธ GC์์ ์๋์ผ๋ก ์ฒ๋ฆฌํด์ฃผ๋๊ฒ ์๋ค๊ฐ ๋ง์ง ์๋๋ค.
์ฆ ์ด๋ด ๋์๋ ๋๋ฌด๋ฅผ ๋ชจ๋ ๋ ๋๋ง์ ์๋ฃํด์ ๋์ด์ ๋๋ฌด๋ฅผ ์์ฑํ ์ผ์ด ์๋ค๋ฉด ๋ฐ๋์ TreeModelFactory์ ์์กดํด์๋ Flyweight Pool์ ๋น์์ค ํ์๊ฐ ์๋ ๊ฒ์ด๋ค.
๊ทธ๋์ผ ์ธ์คํด์ค์ ๋ํ ์ฐธ์กฐ๋ฅผ ์์ TreeModel ์ธ์คํด์ค๋ค์ด GC์ ์ํด ๋ฉ๋ชจ๋ฆฌ ์ฒญ์๊ฐ ๋๊ฒ ๋๋ค.
๊ตฌ์ฒด์ ์ผ๋ก HashMap์์ ํด๋น ์ธ์คํด์ค๋ฅผ ํฌํจํ๋ ์ํธ๋ฆฌ๋ฅผ ์ญ์ ์์ผ๋ฒ๋ฆฌ๋ฉด ์ธ์คํด์ค์ ๋ํ ์ฐธ์กฐ๋ฅผ ์์จ ์ ์๋ค.
6. ์ค๋ฌด์์ ๋ง๋๋ณด์
String Constant Pool
String Constant Pool ๊ฐ๋ ์ด ๋ฐ๋ก Flyweight Pool ๊ฐ๋ ์ด๋ค.
์๋ฐ๋ String ๋ฐ์ดํฐ์ ๋ํด ๋ณ๋๋ก string constant pool ์์ญ์ ์ ์ฌํ๋ค.
๊ทธ๋์ ๊ฐ์ ๋ฌธ์์ด ๋ฐ์ดํฐ ๋ค์ ์ฌ์ฉ๋ ๋ pool์ ๊ฒ์ฌํด ์๋ค๋ฉด ์ด๋ฅผ ๊ณต์ ํ๋ค.
๋ง์ผ pool์ ์๋ค๋ฉด ์๋ก ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ์ฌ pool์ ๋ฑ๋กํ ํ ์ฌ์ฌ์ฉํ๋ค.
์ฆ, String ํด๋์ค๋ Flyweight ํจํด์ ํตํด ๋ฆฌํฐ๋ด ๋ฌธ์์ด ๋ฐ์ดํฐ์ ๋ํ ์บ์ฑ์ ํ๊ณ ์๋ ๊ฒ์ด๋ค.
๋ํ String ํด๋์ค๋ ๋ถ๋ณ(immutable) ๊ฐ์ฒด ํน์ฑ์ ๊ฐ์ง๊ณ ์๋ค.

// ๋ฌธ์์ด ๋ฆฌํฐ๋ด์ String Pool์ ์ ์ฅ๋๋ Flyweight ํจํด์ ์ด์ฉํ๋ค.
String str1 = "Hello";
String str2 = "Hello";
// ๋ ์ฃผ์๊ฐ์ด ๊ฐ๋ค๋ ๋ง์ ๋ฉ๋ชจ๋ฆฌ์ ํ๋์ ๋ฐ์ดํฐ๋ง ์ ์ฌ๋๊ณ ์ด๋ฅผ ๊ณต์ ํ๊ณ ์๋ค๋ ๋ฐ์ฆ
System.out.println(str1 == str2); // true
// new ์ฐ์ฐ์๋ฅผ ์ด์ฉํ ๋ฐฉ์์ Flyweight ํจํด์ ์ ์ฉํ์ง ์๋๋ค.
String str3 = new String("Hello");
String str4 = new String("Hello");
// ์๋ก ๋ค๋ฅธ ํ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ๋ ๋ฐ์ดํฐ์ด๋ ๋ ์ฃผ์๊ฐ์ ๋ค๋ฅด๋ค
System.out.println(str3 == str4); // false
Integer์ valueOf()
์๋ฐ์ Interger ํด๋์ค์valueOf() ๋ฉ์๋๋ ์ ์ ํฉํ ๋ฆฌ ๋ฉ์๋๋ก์,valueOf() ๋ฉ์๋๋ฅผ ํตํด ๊ฐ์ ํ ๋นํ๋ฉด Flyweight ํจํด์ ํตํด ์บ์๋๊ฒ ๋๋ค.
valueOf() ๋ฉ์๋๊ฐ ํธ์ถ ๋์์ ๋ ์์ฒญ๋ Integer ๊ฐ์ด -128 ~ 127 ๋ฒ์์ ์ ์๋ผ๋ฉด ์บ์ฑ์ ์ด์ฉํ๋๋ก ์ค๊ณ ๋์ด์๋ค.
Integer ๋ฟ๋ง ์๋๋ผ Double์ด๋ Boolean ๊ฐ์ Wrapper ํด๋์ค๋ค๋ ๋ง์ฐฌ๊ฐ์ง๋ก ์ ์ฉ๋๋ค.


// valueOf ์ ์ ํฉํ ๋ฆฌ ๋ฉ์๋๋ก ์๋ฅผ ๋ฑ๋กํ๋ฉด ์บ์๋จ
// auto boxing์ผ๋ก Integer i1 = 100; ์ผ๋ก ์ ์ธํ์ฌ๋ ๋๊ฐ์
Integer i1 = Integer.valueOf(100);
Integer i2 = Integer.valueOf(100);
System.out.println(i1 == i2); // true
// ์์ฑ์๋ก ์๋ฅผ ๋ฑ๋กํ๋ฉด ์บ์ ์๋จ
Integer i3 = new Integer(100);
Integer i4 = new Integer(100);
System.out.println(i3 == i4); // false
// -128 ~ 127 ๋ ์บ์ ๋จ
Integer i1 = Integer.valueOf(100);
Integer i2 = Integer.valueOf(100);
System.out.println(i1 == i2); // true
// -128 ~ 127 ๋ฅผ ๋์ด์ ์๋ ์บ์ ์๋จ
Integer i3 = Integer.valueOf(1000);
Integer i4 = Integer.valueOf(1000);
System.out.println(i3 == i4); // false
7. ์๋ ๊ทผ๋ฐ ์ด๊ฑฐ ๋ ์ด๋์ ๋ง์ด ๋ฃ์ง ์์๋?
์ฑ๊ธํค ํจํด๋ ๊ฐ์ฒด ํ๋๋ง ์์ฑํ๊ณ ํ์ฉํ๋ ํจํด์ด๋ผ๊ณ ํ์๋ค.
์ฐจ์ด์ ์ ์ธ์คํด์ค ์์ฑ ์ ํ์ ์ด๋์ ์ ์ดํ๋๋์ ์ฐจ์ด์ด๋ค.
์ฑ๊ธํค ํจํด์ ์ฐ๋ฆฌ๊ฐ ์์ ๊ณต๋ถํ๋ค์ํผ ์ฌ๋ฌ ๋ฐฉ์์ผ๋ก ํด๋์ค ์์ฒด์์ ์ธ์คํด์ค ์์ฑ์ 1๊ฐ๋ก ์ ํํ๋ ๊ฒ์ ๋ฐฐ์ ๋ค.
๊ทธ๋ฌ๋ ํ๋ผ์ด์จ์ดํธ ํจํด์ ์ฑ๊ธํค์ผ๋ก ๋์ด์์ง ์์ ํด๋์ค๋ฅผ(์ธ์คํด์ค ์์ฑ ์์ฒด๋ ์ฌ๋ฌ๊ฐ ํ ์ ์์) ํฉํ ๋ฆฌ์์ ์์ฑ๊ณผ ๊ด๋ฆฌ๋ฅผ ํ๋ ๊ฒ์ด๋ค.
๋๋ฌด์์ ์์ ์ดํด๋ณด๋ฉด ๋ถ๋ณ ๊ฐ์ฒด์ธ TreeModelํด๋์ค ์์ฒด๊ฐ ์ฑ๊ธํค์ผ๋ก ๋์ด์๋ค๋ฉด ํ๋์ mesh , texture ๊ฐ๋ง ๊ฐ์ง ์ ์๊ฒ ๋ ๊ฒ์ด๋ค.
๊ทธ๋ฌ๋ singleton ์ค๋ช ํ ๋๋ ์๋ ค์คฌ๋ DBCP์ฒ๋ผ ์ฌ๊ธฐ์ ํฉํ ๋ฆฌ ํ ์์ฒด๋ ์ฑ๊ธํค์ผ๋ก ๊ด๋ฆฌ๋ ์ ์์ ๊ฒ์ด๋ค.
flyweight pattern
1. Flyweight
Fly(๊ฐ๋ฒผ์ด) + Weight(๋ฌด๊ฒ)๋ฅผ ๋ปํ๋ฉฐ, ๋ณต์ฑ์ ์ฒด๊ธ์์ ์ ๋๋์๋ค.
๋ชจ๋ ๊ฐ์ฒด๋ฅผ ์ผ์ผํ ์ธ์คํด์คํ ํ์ง์๊ณ ์ฌ์ฌ์ฉํ ์ ์๋ ๊ฐ์ฒด๋ ์ฌ์ฌ์ฉํจ์ผ๋ก์จ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ฐ๋ณ๊ฒ ๋ง๋ ๋ค๋ ์๋ฏธ๋ก์ ์ฐ์ธ๋ค๊ณ ๋ณด๋ฉด ๋๋ค.
โ ๊ฐ๋ณ๊ฒ ๋ง๋ ๋ค!

๊ณต์ ๋ ์์๊ณผ ๊ทธ๋ ์ง ์์ ์์์ ์ฌ์ฉ๋ ์ฐจ์ด
2. Flyweight ํจํด ๊ตฌ์กฐ
![]() |
![]() |
---|
Flyweight : ๊ฒฝ๋ ๊ฐ์ฒด๋ฅผ ๋ฌถ๋ ์ธํฐํ์ด์ค
ConcreteFlyweight : ๊ณต์ ๊ฐ๋ฅํ์ฌ ์ฌ์ฌ์ฉ๋๋ ๊ฐ์ฒด(intrinsic state)
UnsahredConcreteFlyweight: ๊ณต์ ๋ถ๊ฐ๋ฅํ ๊ฐ์ฒด (extrinsic state)
FlyweightFactory : ๊ฒฝ๋ ๊ฐ์ฒด๋ฅผ ๋ง๋๋ ๊ณต์ฅ ์ญํ ๊ณผ ์บ์ ์ญํ ์ ๊ฒธ๋นํ๋ Flyweight ๊ฐ์ฒด ๊ด๋ฆฌ ํด๋์ค
- GetFlyweight() ๋ฉ์๋๋ ํฉํ ๋ฆฌ ๋ฉ์๋ ์ญํ ์ ํ๋ค๊ณ ๋ณด๋ฉด ๋๋ค.๋ง์ผ ๊ฐ์ฒด๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ์กด์ฌํ๋ฉด ๊ทธ๋๋ก ๊ฐ์ ธ์ ๋ฐํํ๊ณ , ์๋ค๋ฉด ์๋ก ์์ฑํด ๋ฐํํ๋ค
Client : ํด๋ผ์ด์ธํธ๋ FlyweightFactory๋ฅผ ํตํด Flyweight ํ์
์ ๊ฐ์ฒด๋ฅผ ์ป์ด ์ฌ์ฉํ๋ค.
3. Flyweight pattern ์์ ์ฃผ์ํ ์
๋ณด๋ค์ํผ ๊ตฌํ ๊ฐ์ฒด์ ์ํ๊ฐ ์ค์ํ๋ค.
intrinsic ์ extrinsic ์ํ
โ intrinsic('๊ณ ์ ํ, ๋ณธ์ง์ ์ธโ)ํ ๊ฐ์ฒด : ์ฅ์๋ ์ํฉ์ ์์กดํ์ง ์๊ธฐ ๋๋ฌธ์ ๊ฐ์ด ๊ณ ์ ๋์ด ๊ณต์ ํ ์ ์๋ ๊ฐ์ฒด
extrinsic('์ธ์ ์ธ, ๋น๋ณธ์ง์ ์ธโ)ํ ๊ฐ์ฒด : ์ฅ์๋ ์ํฉ์ ์์กดํ๊ธฐ ๋๋ฌธ์ ๋งค๋ฒ ๊ฐ์ด ๋ฐ๋์ด ๊ณต์ ํ ์ ์๋ ๊ฐ์ฒด
๊ฐ์ฒด๋ค์ ์ํ๋ฅผ ์ ๋ถ๋ฆฌํด์ ์ ์ฉํด์ผํ๋ค.
a. ํญํ ํผํ๊ธฐ ๊ฒ์ ์์

ํญํ ๊ฐ๊ฐ์ ํ๋์ ๊ฐ์ฒด
- ํญํ ๊ฐ์ฒด๋ค์ ์ผ์ผํ new ๋ฅผ ํตํด ์ธ์คํด์คํํ๋ฉด?
- ๊ฐ์ฒด๋ฅผ ์์ฑ ํ ๋๋ง๋ค ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฐจ์งํ๊ฒ ๋์ด ๊ฒ์์ด ๋ฌด๊ฑฐ์์ง ๊ฒ
- ์ด์ฐจํผ ๋จ์ด์ง๋ ํญํ ๊ฐ์ฒด์ ์๊น์๋ ๋ชจ๋ ๊ฐ๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ๊ณ์ ์์ฑํ๋ ๊ฒ์ ์ค๋ณต์ด๋ค.
- ํญํ์ ํ๋ผ์ด์จ์ดํธ๋ก ์ฒ๋ฆฌํจ์ผ๋ก์จ ํญํ ์ธ์คํด์ค๋ ํ๋๋ง ๋ง๋ค๊ณ ๊ณต์ ํ๋ ๋ฐฉ์์ผ๋ก ํ๋ฉด์ ๋ฟ๋ฆฌ๋ฉด ๋๋ค.
โ ๏ธ ์ฃผ์์ !
ํญํ ์์ ์์ intrinsic ์ํ์ ๋ณด์ extrinsic ์ํ์ ๋ณด๋ฅผ ๋ถ๋ฆฌํด์ ์๊ฐํด๋ณด์.
ํญํ์ด ๊ฐ๊ณ ์๋ ์ ๋ณด ๋ชฉ๋ก์ ๋ค์๊ณผ ๊ฐ๋ค.
- ํญํ ๋ชจ์
- ํญํ ์๊น
- ํญํ x, y ์ขํ ์์น
์ฌ๊ธฐ์ 1๋ฒ 2๋ฒ์ ํญํ์ ๋ณธ์ง์ ์ธ ๊ณ ์ ํ ์ํ๋ฅผ ๋ํ๋ด๊ธฐ ๋๋ฌธ์ ์ฌ๋ฌ๊ณณ์ ๊ณต์ ๊ฐ ๊ฐ๋ฅํ๋ค.
๋ฐ๋ฉด, ์์น๊ฐ์ ์ค์๊ฐ์ผ๋ก ๋ณํํ๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ์บ์ํ์ฌ ๊ณต์ ํ ์๋ ์๋ค.
์ด๋ฅผ flyweight pattern์ ์ ์ฉํด๋ณด์๋ฉด,
ConcreteFlyweight๊ฐ์ฒด์๋ ๊ณ ์ ์ ์ ๋ณด์ธ 1,2๋ฒ์ด ํฌํจ๋๊ฒ ๋ ๊ฒ์ด๊ณ ,
UnsharedConcreteFlyweight๊ฐ์ฒด์๋ ๋น ๊ณ ์ ์ ์ ๋ณด์ธ 3๋ฒ์ด ํฌํจ๋๊ฒ ๋ ๊ฒ์ด๋ค.
๊ทธ๋ฆฌ๊ณ ์ด ๋ ํญํ ๊ฐ์ฒด๋ค์ FlyweightFactory๊ฐ ์์ฑํ๊ณ ๊ด๋ฆฌํ๊ฒ ๋๋ ๊ฒ์ด๋ค.
4. ํน์ง
a. ์ ์ฉ์๊ธฐ
- ์ดํ๋ฆฌ์ผ์ด์ ์ ์ํด ์์ฑ๋๋ ๊ฐ์ฒด์ ์๊ฐ ๋ง์ ์ ์ฅ ๋น์ฉ์ด ๋์์ง ๋
- ์์ฑ๋ ๊ฐ์ฒด๊ฐ ์ค๋๋๋ก ๋ฉ๋ชจ๋ฆฌ์ ์์ฃผํ๋ฉฐ ์ฌ์ฉ๋๋ ํ์๊ฐ ๋ง์๋
- ๊ณตํต์ ์ธ ์ธ์คํด์ค๋ฅผ ๋ง์ด ์์ฑํ๋ ๋ก์ง์ด ํฌํจ๋ ๊ฒฝ์ฐ
- ์๋ฒ ๋๋์ ๊ฐ์ด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ต์ํ์ผ๋ก ์ฌ์ฉํด์ผํ๋ ๊ฒฝ์ฐ์ ํ์ฉ โ ์ ์ด์ ํ๋ฝ๋ ์์์ ์ ์์ฒด๊ฐ ์ ๋ค
b. ์ฅ์
- ์ดํ๋ฆฌ์ผ์ด์ ์์ ์ฌ์ฉํ๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ค์ผ ์ ์๋ค.
- ํ๋ก๊ทธ๋จ ์๋๋ฅผ ๊ฐ์ ํ ์ ์๋ค.
- new๋ก ์ธ์คํด์คํ ํ๋ฉด ๋ฐ์ดํฐ๊ฐ ์์ฑ๋๊ณ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฌ๋๋ ์์ฃผ ์ฝ๊ฐ์ ์๊ฐ์ด ์์๋๋ค.
- ๊ฐ์ฒด๋ฅผ ๊ณต์ ํ๋ฉด ์ธ์คํด์ค๋ฅผ ๊ฐ์ ธ์ค๊ธฐ๋ง ํ๋ฉด ๋๊ธฐ ๋๋ฌธ์ ๋ฉ๋ชจ๋ฆฌ ๋ฟ๋ง ์๋๋ผ ์๋๋ ํฅ์์ํฌ ์ ์๊ฒ ๋๋ ๊ฒ์ด๋ค.
c. ๋จ์
- ์ฝ๋์ ํน์ก์ฑ ์ฆ๊ฐ
5. ๋ง์ธํฌ๋ํํธ์ ๋๋ฌด์ฌ๊ธฐ ์์
๋ง์ธํฌ๋ํํธ์ ์ฒ์ ๊ตฌํํ๊ธฐ ์ํด์ ์งํ(Terrain)์ ๋๋ฌด ๊ฐ์ฒด๋ค์ ์ฌ์ผ๋ ค๊ณ ํ๋ค.

๋๋ฌด์ ์ข ๋ฅ
๋๋ฌด ๊ฐ์ฒด์ ํ์ํ ๋ฐ์ดํฐ๋ ๋ค์๊ณผ ๊ฐ๋ค.
- ๋๋ฌด ์ข ๋ฅ
- ์ค๊ธฐ, ๊ฐ์ง, ์์ ํํ๋ฅผ ๋ํ๋ด๋ ํด๋ฆฌ๊ณค ๋ฉ์ (mesh) โ ํํ ๊ด๋ จ
- ๋๋ฌด ๊ป์ง ํ ์ค์ณ (texture) โ ํํ ๊ด๋ จ
- ์ ์ฌ๊ท ํ ์ค์ณ (texture) โ ํํ ๊ด๋ จ
- ์ฒ์์์ ์์น ๋งค๊ฐ๋ณ์
No Clean Code

์์ ์์์ ๋ค์ด์๋ ๋ด์ฉ์ ๋ชจ๋ ๋๋ฌด๊ฐ ๋์ผํ๋ค.
Memory.java : ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ์ฒดํฌ์ฉ ํด๋์ค
class Memory {
public static long size = 0; // ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋
public static void print() {
System.out.println("์ด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ : " + Memory.size + "MB");
}
}
Tree.java : Tree ๊ฐ์ฒด ํด๋์ค
class Tree {
long objSize = 100; // 100MB
String type; // ๋๋ฌด ์ข
๋ฅ
Object mesh; // ๋ฉ์ฌ
Object texture; // ๋๋ฌด ๊ป์ง + ์์ฌ๊ท ํ
์ค์ณ
// ์์น ๋ณ์
double position_x;
double position_y;
public Tree(String type, Object mesh, Object texture, double position_x, double position_y) {
this.type = type;
this.mesh = mesh;
this.texture = texture;
this.position_x = position_x;
this.position_y = position_y;
// ๋๋ฌด ๊ฐ์ฒด๋ฅผ ์์ฑํ์์ผ๋ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ ํฌ๊ธฐ ์ฆ๊ฐ
Memory.size += this.objSize;
}
}
Terrain.java : ์งํ ํด๋์ค, ๋๋ฌด๋ฅผ ์์ฑํ๋ ํด๋ผ์ด์ธํธ ๊ฐ์ฒด
// Client
class Terrain {
// ์งํ ํ์ผ ํฌ๊ธฐ
static final int CANVAS_SIZE = 10000;
// ๋๋ฌด๋ฅผ ๋ ๋๋ง
public void render(String type, Object mesh, Object texture, double position_x, double position_y) {
// ๋๋ฌด๋ฅผ ์งํ์ ์์ฑ
Tree tree = new Tree(
type, // ๋๋ฌด ์ข
๋ฅ
mesh, // mesh
texture, // texture
Math.random() * CANVAS_SIZE, // position_x
Math.random() * CANVAS_SIZE // position_y
);
System.out.println("x:" + tree.position_x + " y:" + tree.position_y + " ์์น์ " + type + " ๋๋ฌด ์์ฑ ์๋ฃ");
}
}
main
public static void main(String[] args) {
// ์งํ ์์ฑ
Terrain terrain = new Terrain();
// ์งํ์ Oak ๋๋ฌด 5 ๊ทธ๋ฃจ ์์ฑ
for (int i = 0; i < 5; i++) {
terrain.render(
"Oak", // type
new Object(), // mesh
new Object(), // texture
Math.random() * Terrain.CANVAS_SIZE, // position_x
Math.random() * Terrain.CANVAS_SIZE // position_y
);
}
// ์งํ์ Acacia ๋๋ฌด 5 ๊ทธ๋ฃจ ์์ฑ
for (int i = 0; i < 5; i++) {
terrain.render(
"Acacia", // type
new Object(), // mesh
new Object(), // texture
Math.random() * Terrain.CANVAS_SIZE, // position_x
Math.random() * Terrain.CANVAS_SIZE // position_y
);
}
// ์งํ์ Jungle ๋๋ฌด 5 ๊ทธ๋ฃจ ์์ฑ
for (int i = 0; i < 5; i++) {
terrain.render(
"Jungle", // type
new Object(), // mesh
new Object(), // texture
Math.random() * Terrain.CANVAS_SIZE, // position_x
Math.random() * Terrain.CANVAS_SIZE // position_y
);
}
// ์ด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ฅ ์ถ๋ ฅ
Memory.print();
}

๊ฐ ์ธ์ข ๋ฅ์ ๋๋ฌด๋ฅผ 5๊ฐ์ฉ 100mb๋ฅผ ๊ณฑํ๋ฉด ์ด 1500mb ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ฌ์ฉ๋๊ฒ ๋๋ ๊ฒ.
Clean Code โ Flyweight pattern ์ ์ฉ

์ต์ ํ์ ํต์ฌ์ ๋๋ฌด๊ฐ ์๋ฐฑ ๊ทธ๋ฃจ ๋๊ฒ ์๋๋ค ํด๋ ๋๋ถ๋ถ ๋น์ทํ๊ฒ ๋ณด์ธ๋ค๋ ๊ฒ์ด๋ค.
์ฆ, ๋๋ฌด๋ฅผ ์์ฑํ๋๋ฐ ์ฌ์ฉ๋ mesh, texture๋ฅผ ์ฌ์ฌ์ฉํ์ฌ ํํํด๋ ์ด์ฐจํผ ๊ฐ์ ๋๋ฌด์ด๋ ๋ฌธ์ ๊ฐ ์๋ ๊ฒ์ด๋ค.
๋ฐ๋ผ์ ๊ณตํต์ผ๋ก ์ฌ์ฉ๋ ๋ชจ๋ธ ๋ฐ์ดํฐ, ์ค์๊ฐ์ผ๋ก ๋ณํ๋ ์์น ๋งค๊ฐ๋ณ์๋ฅผ ๋ถ๋ฆฌํ์ฌ ๊ฐ์ฒด๋ฅผ ๊ตฌ์ฑํ๋ค.
์ด๋ ๊ฒ ๋๋ฉด ์งํ์์ ๋๋ฌด๋ฅผ ๊ตฌํํ ๋ ๋๋ฌด ๋ชจ๋ธ ์ธ์คํด์ค ํ๋๋ฅผ ๊ณต์ ๋ฐ๊ณ ์์น ๋งค๊ฐ๋ณ์๋ง ๋ค๋ฅด๊ฒ ์ค์ ํด์ฃผ๋ฉด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ ๋ฐ ์ด์ ์ค์ผ ์ ์์ ๊ฒ์ด๋ค. โ ๋๋ฌด๊ฐ ๋ง์ผ๋ฉด ๋ง์ ์๋ก ์ ์ฝ๋๋ค.
- ์ฝ๊ฒ ๋งํด, ์ค์๊ฐ์ผ๋ก ๋ณํ๋ ์์น๊ฐ๋ณด๋ค ๋๋ฌด๋ฅผ ํํํ๋ ๋ฉ์, ์์ฌ๊ท ๋ฑ์ ๊ฐ์ ์ค์๊ฐ์ผ๋ก ๋ณํ ํ์์์ด ์ฌ์ฌ์ฉํด๋ ์๊ด์๋ค๋ ๊ฑฐ๋ค.

1. intrinsic ๊ฐ์ฒด์ extrinsic ๊ฐ์ฒด ๋ถ๋ฆฌํ๊ธฐ
๋งํฌ ๊ฒ์ ๋ด์์ ๋๊ฐ์ ๋ฉ์์ ๋๋ฌด๊ป์ง ํ ์ค์ณ๋ฅผ ์ผ์ผํ ์ฌ๋ฌ๋ฒ ๋ฉ๋ชจ๋ฆฌ์ ์ฌ๋ฆด ์ด์ ๊ฐ ์๊ธฐ ๋๋ฌธ์ ๊ณต์ ๋๋ ๋๋ฌด ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ๊ธฐ์กด Tree ํด๋์ค์์ ๋ฐ๋ก ๋นผ์ค๋ค.
instrinsic : mesh, texture
extrinsic : position ์ขํ
TreeModel.java : ๋ถ๋ณ๊ฐ์ฒด
// ConcreteFlyweight - ํ๋ผ์ด์จ์ดํธ ๊ฐ์ฒด๋ ๋ถ๋ณ์ฑ์ ๊ฐ์ ธ์ผํ๋ค. ๋ณ๊ฒฝ๋๋ฉด ๋ชจ๋ ๊ฒ์ ์ํฅ์ ์ฃผ๊ธฐ ๋๋ฌธ์ด๋ค.
final class TreeModel { // final ์ ํตํด ๋ถ๋ณ ๊ฐ์ฒด๋ก ๋ง๋ค์ด์ค
// ๋ฉ์, ํ
์ค์ณ ์ด ์ฌ์ด์ฆ
long objSize = 90; // 90MB
String type; // ๋๋ฌด ์ข
๋ฅ
Object mesh; // ๋ฉ์ฌ
Object texture; // ๋๋ฌด ๊ป์ง + ์์ฌ๊ท ํ
์ค์ณ
public TreeModel(String type, Object mesh, Object texture) {
this.type = type;
this.mesh = mesh;
this.texture = texture;
// ๋๋ฌด ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฌํ์ผ๋ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ ํฌ๊ธฐ ์ฆ๊ฐ
Memory.size += this.objSize;
}
}
Tree.java : ๊ฐ๋ณ ๊ฐ์ฒด
// UnsahredConcreteFlyweight
class Tree {
// ์ฃํ๊ฐ๊ณผ ๋๋ฌด ๋ชจ๋ธ ์ฐธ์กฐ ๊ฐ์ฒด ํฌ๊ธฐ๋ฅผ ํฉ์น ์ฌ์ด์ฆ
long objSize = 10; // 10MB
// ์์น ๋ณ์
double position_x;
double position_y;
// ๋๋ฌด ๋ชจ๋ธ
TreeModel model; // ํฉ์ฑ์ ํตํด ๊ด๊ณ ๋งบ์ด์ค
public Tree(TreeModel model, double position_x, double position_y) {
this.model = model;
this.position_x = position_x;
this.position_y = position_y;
// ๋๋ฌด ๊ฐ์ฒด๋ฅผ ์์ฑํ์์ผ๋ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ ํฌ๊ธฐ ์ฆ๊ฐ
Memory.size += this.objSize;
}
}
2. Flyweight ํฉํ ๋ฆฌ ๋ง๋ค๊ธฐ
๋๋ฌด ๋ชจ๋ธ ๊ฐ์ฒด์ Flyweight๋ฅผ ์ ์ฉ ํ์ผ๋ ์ด๋ฅผ ์์ฑ ๋ฐ ๊ด๋ฆฌํ FlyweightFactory ํด๋์ค๋ฅผ ๋ง๋ ๋ค.
โ ํ๋ผ์ด์จ์ดํธ ํฉํ ๋ฆฌ์ ํต์ฌ
- Flyweight Pool : HashMap ์ปฌ๋ ์ ์ ํตํด ํค(key) ์ ๋๋ฌด ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ์ ์ฅํ๋ ์บ์ ์ ์ฅ์ ์ญํ
- getInstance ๋ฉ์๋ : Pool์ ๊ฐ์ ธ์ค๊ณ ์ ํ๋ ๊ฐ์ฒด๊ฐ ์๋์ง ๊ฒ์ฌ๋ฅผ ํ์ฌ ์์ผ๋ฉด ๊ทธ๋๋ก ๋ฐํ, ์์ผ๋ฉด ์๋ก ์์ฑ
// FlyweightFactory
class TreeModelFactory {
// Flyweight Pool - TreeModel ๊ฐ์ฒด๋ค์ Map์ผ๋ก ๋ฑ๋กํ์ฌ ์บ์ฑ
private static final Map<String, TreeModel> cache = new HashMap<>(); // static final ์ด๋ผ Thread-Safe ํจ
// static factory method
public static TreeModel getInstance(String key) {
// ๋ง์ฝ ์บ์ ๋์ด ์๋ค๋ฉด
if(cache.containsKey(key)) {
return cache.get(key); // ๊ทธ๋๋ก ๊ฐ์ ธ์ ๋ฐํ
} else {
// ์บ์ ๋์ด์์ง ์์ผ๋ฉด ๋๋ฌด ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ์๋ก ์์ฑํ๊ณ ๋ฐํ
TreeModel model = new TreeModel(
key,
new Object(),
new Object()
);
System.out.println("-- ๋๋ฌด ๋ชจ๋ธ ๊ฐ์ฒด ์๋ก ์์ฑ ์๋ฃ --");
// ์บ์์ ์ ์ฌ
cache.put(key, model);
return model;
}
}
}
3. Client ์ต์ ํ
๊ธฐ์กด Terrian ํด๋์ค์ render() ๋ฉ์๋๋ ๋จ์ํ๊ฒ ์ฌ์ฉ์๋ก๋ถํฐ ๋งค๊ฐ๋ณ์๋ฅผ ๋ฐ์ ๊ทธ๋๋ก tree๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
๊ทธ๋ฌ๋ ์ง๊ธ ๊ธฐ์กด Tree๊ฐ์ฒด๋ฅผ ๋ฐ๋ก TreeModel๋ก ๋๋๊ณ , TreeModelFactory๊น์ง ์์ฑํ์ผ๋ ์ด๋ฅผ ์ด์ฉํ๋ ํด๋ผ์ด์ธํธ ์ฝ๋๋ฅผ ์ต์ ํ ํด์ฃผ์ด์ผํ๋ค.
โ Flyweight๋ฅผ ์ด์ฉํ ์ต์ ํ ์์
- ๋จผ์ TreeModel์์ ๊ณต์ ๋๊ณ ์๋ ๋๋ฌด ๋ชจ๋ธ ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์จ๋ค. (์บ์์ ์๋ค๋ฉด ์๋ก ์์ฑ)
- ๊ฐ์ ธ์จ ๋๋ฌด ๋ชจ๋ธ๊ณผ ์ขํ๊ฐ์ ์ด์ฉํด ๋๋ฌด ๊ฐ์ฒด๋ฅผ ์๋ก ์์ฑํ๋ค.
๊ณต์ ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์ ์ฌ์ฉํจ์ผ๋ก์จ ์ธ๋ฐ์๋ mesh ๋ฐ texture ๋ญ๋น๋ฅผ ๋ฐฉ์งํ๋ค.
Terrain.java
// Client
class Terrain {
// ์งํ ํ์ผ ํฌ๊ธฐ
static final int CANVAS_SIZE = 10000;
// ๋๋ฌด๋ฅผ ๋ ๋๋ง
public void render(String type, double position_x, double position_y) {
// 1. ์บ์ ๋์ด ์๋ ๋๋ฌด ๋ชจ๋ธ ๊ฐ์ฒด ๊ฐ์ ธ์ค๊ธฐ
TreeModel model = TreeModelFactory.getInstance(type);
// 2. ์ฌ์ฌ์ฉํ ๋๋ฌด ๋ชจ๋ธ ๊ฐ์ฒด์ ๋ณํํ๋ ์์ฑ์ธ ์ขํ๊ฐ์ผ๋ก ๋๋ฌด ์์ฑ
Tree tree = new Tree(model, position_x, position_y);
System.out.println("x:" + tree.position_x + " y:" + tree.position_y + " ์์น์ " + type + " ๋๋ฌด ์์ฑ ์๋ฃ");
}
}
main
public static void main(String[] args) {
// ์งํ ์์ฑ
Terrain terrain = new Terrain();
// ์งํ์ Oak ๋๋ฌด 5 ๊ทธ๋ฃจ ์์ฑ
for (int i = 0; i < 5; i++) {
terrain.render(
"Oak", // type
Math.random() * Terrain.CANVAS_SIZE, // position_x
Math.random() * Terrain.CANVAS_SIZE // position_y
);
}
// ์งํ์ Acacia ๋๋ฌด 5 ๊ทธ๋ฃจ ์์ฑ
for (int i = 0; i < 5; i++) {
terrain.render(
"Acacia", // type
Math.random() * Terrain.CANVAS_SIZE, // position_x
Math.random() * Terrain.CANVAS_SIZE // position_y
);
}
// ์งํ์ Jungle ๋๋ฌด 5 ๊ทธ๋ฃจ ์์ฑ
for (int i = 0; i < 5; i++) {
terrain.render(
"Jungle", // type
Math.random() * Terrain.CANVAS_SIZE, // position_x
Math.random() * Terrain.CANVAS_SIZE // position_y
);
}
// ์ด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ฅ ์ถ๋ ฅ
Memory.print();
}

ํจํด ์ ์ฉ ์ ์๋ 1500mb ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ๋ค์ด๊ฐ์ผ๋, ํจํด ์ ์ฉ ํ์๋ 420mb๋ก ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ํ ์ค์ด๋ค์๋ค.
์ ์๋ ๊ณ์ ๋๋ฌด๋ฅผ ์์ฑํ๋ ๋ฐ๋ฉด์, ๋๋ฌด ๋ชจ๋ธ์ ๋ฐ๋ก ํ๋ผ์ด์จ์ดํธ๋ก ๋ถ๋ฆฌํจ์ผ๋ก์จ ์ค๋ณต๋ ๊ฐ๋ค์ ๊ณต์ ์์ผ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๊ผ๋ค.
์ด์ฒ๋ผ ๊ณต์ ํ ์ ์๋ intrinsic ์ํ์ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฆฌํ์ฌ ์บ์ฑํจ์ผ๋ก์จ ํ๋ก๊ทธ๋จ์ ์ต์ ํํ๋ ๊ฒ์ด ์ค์ํ๋ค.
์ฃผ์์ฌํญ - GC
์ฐ๋ฆฌ๊ฐ ๊ตฌํํ ์์ ์์๋ TreeModelFactory์์ HashMap์ ์ด์ฉํด TreeModel์ ์ธ์คํด์ค๋ฅผ ์บ์ฑํ์ฌ ๊ด๋ฆฌํ๋ค.
์ด์ฒ๋ผ โ์ธ์คํด์ค๋ฅผ ๊ด๋ฆฌโํ๋ ๊ธฐ๋ฅ์ ์๋ฐ ํ๋ก๊ทธ๋๋ฐ์์ ๊ตฌํํ์ฌ ์ฌ์ฉํ ๋์๋ ๋ฐ๋์!! โ๊ด๋ฆฌ๋๊ณ ์๋ ์ธ์คํด์ค๋ GC(Garbage Collection) ์ฒ๋ฆฌ๋์ง ์๋๋คโ๋ ์ ์ ์ฃผ์ํด์ผํ๋ค.
๊ทธ๋ฐ๋ฐ ์ด์ฐ๋ณด๋ฉด ๋น์ฐํ ์ด์น์ด๋ค. ์ธ์คํด์ค๋ฅผ ๊ด๋ฆฌํ๋ค๋ ๊ฒ ์์ฒด๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ๋๊ณ ๋ด๊ฐ ๊ณต์ ํ ๊ฒ์ด๋ผ๊ณ ํด๋จ๋๋ฐ ์ด๊ฑธ GC์์ ์๋์ผ๋ก ์ฒ๋ฆฌํด์ฃผ๋๊ฒ ์๋ค๊ฐ ๋ง์ง ์๋๋ค.
์ฆ ์ด๋ด ๋์๋ ๋๋ฌด๋ฅผ ๋ชจ๋ ๋ ๋๋ง์ ์๋ฃํด์ ๋์ด์ ๋๋ฌด๋ฅผ ์์ฑํ ์ผ์ด ์๋ค๋ฉด ๋ฐ๋์ TreeModelFactory์ ์์กดํด์๋ Flyweight Pool์ ๋น์์ค ํ์๊ฐ ์๋ ๊ฒ์ด๋ค.
๊ทธ๋์ผ ์ธ์คํด์ค์ ๋ํ ์ฐธ์กฐ๋ฅผ ์์ TreeModel ์ธ์คํด์ค๋ค์ด GC์ ์ํด ๋ฉ๋ชจ๋ฆฌ ์ฒญ์๊ฐ ๋๊ฒ ๋๋ค.
๊ตฌ์ฒด์ ์ผ๋ก HashMap์์ ํด๋น ์ธ์คํด์ค๋ฅผ ํฌํจํ๋ ์ํธ๋ฆฌ๋ฅผ ์ญ์ ์์ผ๋ฒ๋ฆฌ๋ฉด ์ธ์คํด์ค์ ๋ํ ์ฐธ์กฐ๋ฅผ ์์จ ์ ์๋ค.
6. ์ค๋ฌด์์ ๋ง๋๋ณด์
String Constant Pool
String Constant Pool ๊ฐ๋ ์ด ๋ฐ๋ก Flyweight Pool ๊ฐ๋ ์ด๋ค.
์๋ฐ๋ String ๋ฐ์ดํฐ์ ๋ํด ๋ณ๋๋ก string constant pool ์์ญ์ ์ ์ฌํ๋ค.
๊ทธ๋์ ๊ฐ์ ๋ฌธ์์ด ๋ฐ์ดํฐ ๋ค์ ์ฌ์ฉ๋ ๋ pool์ ๊ฒ์ฌํด ์๋ค๋ฉด ์ด๋ฅผ ๊ณต์ ํ๋ค.
๋ง์ผ pool์ ์๋ค๋ฉด ์๋ก ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ์ฌ pool์ ๋ฑ๋กํ ํ ์ฌ์ฌ์ฉํ๋ค.
์ฆ, String ํด๋์ค๋ Flyweight ํจํด์ ํตํด ๋ฆฌํฐ๋ด ๋ฌธ์์ด ๋ฐ์ดํฐ์ ๋ํ ์บ์ฑ์ ํ๊ณ ์๋ ๊ฒ์ด๋ค.
๋ํ String ํด๋์ค๋ ๋ถ๋ณ(immutable) ๊ฐ์ฒด ํน์ฑ์ ๊ฐ์ง๊ณ ์๋ค.

// ๋ฌธ์์ด ๋ฆฌํฐ๋ด์ String Pool์ ์ ์ฅ๋๋ Flyweight ํจํด์ ์ด์ฉํ๋ค.
String str1 = "Hello";
String str2 = "Hello";
// ๋ ์ฃผ์๊ฐ์ด ๊ฐ๋ค๋ ๋ง์ ๋ฉ๋ชจ๋ฆฌ์ ํ๋์ ๋ฐ์ดํฐ๋ง ์ ์ฌ๋๊ณ ์ด๋ฅผ ๊ณต์ ํ๊ณ ์๋ค๋ ๋ฐ์ฆ
System.out.println(str1 == str2); // true
// new ์ฐ์ฐ์๋ฅผ ์ด์ฉํ ๋ฐฉ์์ Flyweight ํจํด์ ์ ์ฉํ์ง ์๋๋ค.
String str3 = new String("Hello");
String str4 = new String("Hello");
// ์๋ก ๋ค๋ฅธ ํ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅ๋ ๋ฐ์ดํฐ์ด๋ ๋ ์ฃผ์๊ฐ์ ๋ค๋ฅด๋ค
System.out.println(str3 == str4); // false
Integer์ valueOf()
์๋ฐ์ Interger ํด๋์ค์valueOf() ๋ฉ์๋๋ ์ ์ ํฉํ ๋ฆฌ ๋ฉ์๋๋ก์,valueOf() ๋ฉ์๋๋ฅผ ํตํด ๊ฐ์ ํ ๋นํ๋ฉด Flyweight ํจํด์ ํตํด ์บ์๋๊ฒ ๋๋ค.
valueOf() ๋ฉ์๋๊ฐ ํธ์ถ ๋์์ ๋ ์์ฒญ๋ Integer ๊ฐ์ด -128 ~ 127 ๋ฒ์์ ์ ์๋ผ๋ฉด ์บ์ฑ์ ์ด์ฉํ๋๋ก ์ค๊ณ ๋์ด์๋ค.
Integer ๋ฟ๋ง ์๋๋ผ Double์ด๋ Boolean ๊ฐ์ Wrapper ํด๋์ค๋ค๋ ๋ง์ฐฌ๊ฐ์ง๋ก ์ ์ฉ๋๋ค.


// valueOf ์ ์ ํฉํ ๋ฆฌ ๋ฉ์๋๋ก ์๋ฅผ ๋ฑ๋กํ๋ฉด ์บ์๋จ
// auto boxing์ผ๋ก Integer i1 = 100; ์ผ๋ก ์ ์ธํ์ฌ๋ ๋๊ฐ์
Integer i1 = Integer.valueOf(100);
Integer i2 = Integer.valueOf(100);
System.out.println(i1 == i2); // true
// ์์ฑ์๋ก ์๋ฅผ ๋ฑ๋กํ๋ฉด ์บ์ ์๋จ
Integer i3 = new Integer(100);
Integer i4 = new Integer(100);
System.out.println(i3 == i4); // false
// -128 ~ 127 ๋ ์บ์ ๋จ
Integer i1 = Integer.valueOf(100);
Integer i2 = Integer.valueOf(100);
System.out.println(i1 == i2); // true
// -128 ~ 127 ๋ฅผ ๋์ด์ ์๋ ์บ์ ์๋จ
Integer i3 = Integer.valueOf(1000);
Integer i4 = Integer.valueOf(1000);
System.out.println(i3 == i4); // false
7. ์๋ ๊ทผ๋ฐ ์ด๊ฑฐ ๋ ์ด๋์ ๋ง์ด ๋ฃ์ง ์์๋?
์ฑ๊ธํค ํจํด๋ ๊ฐ์ฒด ํ๋๋ง ์์ฑํ๊ณ ํ์ฉํ๋ ํจํด์ด๋ผ๊ณ ํ์๋ค.
์ฐจ์ด์ ์ ์ธ์คํด์ค ์์ฑ ์ ํ์ ์ด๋์ ์ ์ดํ๋๋์ ์ฐจ์ด์ด๋ค.
์ฑ๊ธํค ํจํด์ ์ฐ๋ฆฌ๊ฐ ์์ ๊ณต๋ถํ๋ค์ํผ ์ฌ๋ฌ ๋ฐฉ์์ผ๋ก ํด๋์ค ์์ฒด์์ ์ธ์คํด์ค ์์ฑ์ 1๊ฐ๋ก ์ ํํ๋ ๊ฒ์ ๋ฐฐ์ ๋ค.
๊ทธ๋ฌ๋ ํ๋ผ์ด์จ์ดํธ ํจํด์ ์ฑ๊ธํค์ผ๋ก ๋์ด์์ง ์์ ํด๋์ค๋ฅผ(์ธ์คํด์ค ์์ฑ ์์ฒด๋ ์ฌ๋ฌ๊ฐ ํ ์ ์์) ํฉํ ๋ฆฌ์์ ์์ฑ๊ณผ ๊ด๋ฆฌ๋ฅผ ํ๋ ๊ฒ์ด๋ค.
๋๋ฌด์์ ์์ ์ดํด๋ณด๋ฉด ๋ถ๋ณ ๊ฐ์ฒด์ธ TreeModelํด๋์ค ์์ฒด๊ฐ ์ฑ๊ธํค์ผ๋ก ๋์ด์๋ค๋ฉด ํ๋์ mesh , texture ๊ฐ๋ง ๊ฐ์ง ์ ์๊ฒ ๋ ๊ฒ์ด๋ค.
๊ทธ๋ฌ๋ singleton ์ค๋ช ํ ๋๋ ์๋ ค์คฌ๋ DBCP์ฒ๋ผ ์ฌ๊ธฐ์ ํฉํ ๋ฆฌ ํ ์์ฒด๋ ์ฑ๊ธํค์ผ๋ก ๊ด๋ฆฌ๋ ์ ์์ ๊ฒ์ด๋ค.