- ์ธ์คํด์ค๋ฅผ ์ค์ง ํ๋๋ง ์์ฑํ ์ ์๋ ํด๋์ค๋ฅผ ๋งํ๋ค.
- ์ ํ์ ์ธ ์๋ก๋ ํจ์์ ๊ฐ์ ๋ฌด์ํ(stateless) ๊ฐ์ฒด๋ ์ค๊ณ์ ์ ์ผํด์ผ ํ๋ ์์คํ ์ปดํฌ๋ํธ
ํด๋์ค๋ฅผ ์ฑ๊ธํด์ผ๋ก ๋ง๋ค๋ฉด ์ด๋ฅผ ์ฌ์ฉํ๋ ํด๋ผ์ด์ธํธ๋ฅผ ํ ์คํธํ๊ธฐ๊ฐ ์ด๋ ค์์ง ์ ์๋ค.
์ด์ ๋ ํ์
์ ์ธํฐํ์ด์ค๋ก ์ ์ํ ๋ค์ ๊ทธ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํด์ ๋ง๋ ์ฑ๊ธํด์ด ์๋๋ผ๋ฉด ์ฑ๊ธํด ์ธ์คํด์ค๋ฅผ ๊ฐ์ง(MOCK) ๊ตฌํ์ผ๋ก ๋์ฒดํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๋ ๋ฐฉ์ ๋ชจ๋ ์์ฑ์๋ private์ผ๋ก ๊ฐ์ถฐ๋๊ณ , ์ ์ผํ ์ธ์คํด์ค์ ์ ๊ทผํ ์ ์๋ ์๋จ์ผ๋ก
public static ๋ฉค๋ฒ๋ฅผ ํ๋ ๋ง๋ จ
public class Elvis {
// ์ ์ผํ ์ธ์คํด์ค๋ฅผ ์์ฑ
public static final Elvis INSTANCE = new Elvis();
// ์์ฑ์๋ฅผ private์ผ๋ก ์ค์ ํ์ฌ ์ธ๋ถ์์ ์ธ์คํด์ค๋ฅผ ์์ฑํ์ง ๋ชปํ๊ฒ ํจ
private Elvis() {
// ์ด๊ธฐํ ์ฝ๋ (ํ์ํ ๊ฒฝ์ฐ)
}
// Elvis๊ฐ ๋ ๋๋ ํ๋์ ์ ์ํ๋ ๋ฉ์๋
public void leaveTheBuilding() {
// ๊ตฌํ ์ฝ๋
}
}private ์์ฑ์๋ public static final ํ๋์ธ Elvis.INSTANCE๋ฅผ ์ด๊ธฐํํ ๋ ๋ฑ ํ ๋ฒ๋ง ํธ์ถ๋๋ค. public์ด๋ protected ์์ฑ์๊ฐ ์์ผ๋ฏ๋ก Elvis ํด๋์ค๊ฐ ์ด๊ธฐํ๋ ๋ ๋ง๋ค์ด์ง ์ธ์คํด์ค๊ฐ ์ ์ฒด ์์คํ ์์ ํ๋๋ฟ์์ด ๋ณด์ฅ๋๋ค.
- ๋ฆฌํ๋ ์ API: Java์ ๋ฆฌํ๋ ์ API๋ ๋ฐํ์์ ํด๋์ค, ๋ฉ์๋, ํ๋ ๋ฑ์ ์ ๋ณด๋ฅผ ๋์ ์ผ๋ก ์กฐ์ฌํ๊ณ ์กฐ์ํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณต
- AccessibleObject.setAccessible: ์ด ๋ฉ์๋๋
private๋๋protected๋ก ์ค์ ๋ ํ๋๋ ๋ฉ์๋์ ์ ๊ทผํ ์ ์๊ฒ ํด์ค๋ค. ์ฆ, ์ผ๋ฐ์ ์ผ๋ก ์ ๊ทผ์ด ์ ํ๋ ์์์ ์ ๊ทผํ ์ ์๋๋ก ํ์ฉํ๋ค. - ๊ถํ์ด ์๋ ํด๋ผ์ด์ธํธ(์: ํน์ ์ค์ ์ด๋ ๋ณด์ ๊ถํ์ ๊ฐ์ง ์ฝ๋)๋ ๋ฆฌํ๋ ์
์ ์ฌ์ฉํ์ฌ
private์์ฑ์๋ฅผ ํธ์ถํ ์ ์๋ค. ์ด ๊ฒฝ์ฐ, ์ฑ๊ธํด ํจํด์ ์๋๊ฐ ๋ฌด์๋๊ณ , ์ฌ๋ฌ ๊ฐ์ ์ธ์คํด์ค๊ฐ ์์ฑ๋ ์ ์๋ค.
์ด๋ฌํ ๊ณต๊ฒฉ์ ๋ฐฉ์ดํ๋ ค๋ฉด, ์์ฑ์๋ฅผ ์์ ํ์ฌ ๋ ๋ฒ์งธ ๊ฐ์ฒด๊ฐ ์์ฑ๋๋ ค ํ ๋ ์์ธ๋ฅผ ๋์ง๊ฒ ํ๋ฉด ๋จ
- public ํ๋ ๋ฐฉ์์ ํฐ ์ฅ์ ์ ํด๋น ํด๋์ค๊ฐ ์ฑ๊ธํด์์ด API์ ๋ช ๋ฐฑํ ๋๋ฌ๋๋ค๋ ๊ฒ์ด๋ค.
- public static ํ๋๊ฐ final์ด๋ ์ ๋๋ก ๋ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ ์ ์๋ค.
- ๊ฐ๊ฒฐํ๋ค.
public class Elvis {
// ์ ์ผํ ์ธ์คํด์ค๋ฅผ ์์ฑ
private static final Elvis INSTANCE = new Elvis();
// private ์์ฑ์
private Elvis() {
// ์ด๊ธฐํ ์ฝ๋ (ํ์ํ ๊ฒฝ์ฐ)
}
// ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋ ๋ฉ์๋(์๋ก)์ถ๊ฐ๋จ
public static Elvis getInstance() {
return INSTANCE;
}
// Elvis๊ฐ ๋ ๋๋ ํ๋์ ์ ์ํ๋ ๋ฉ์๋
public void leaveTheBuilding() {
// ๊ตฌํ ์ฝ๋
}
}Elvis.getInstance ๋ ํญ์ ๊ฐ์ ๊ฐ์ฒด์ ์ฐธ์กฐ๋ฅผ ๋ฐํํ๋ฏ๋ก ์ 2์ Elvis ์ธ์คํด์ค๋ ๊ฒฐ์ฝ ๋ง๋ค์ด์ง์ง ์๋ค๏ผ์ญ์ ๋ฆฌํ๋ ์
์ ํตํ ์์ธ๋ ๋๊ฐ์ด ์ ์ฉ๋๋ค๏ผ
- (๋ง์์ด ๋ฐ๋๋ฉด) API๋ฅผ ๋ฐ๊พธ์ง ์๊ณ ๋ ์ฑ๊ธํด์ด ์๋๊ฒ ๋ณ๊ฒฝํ ์ ์๋ค๋ ์ : ์ ์ผํ๊ฒ ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋ ํฉํฐ๋ฆฌ ๋ฉ์๋๊ฐ ํธ์ถํ๋ ์ค๋ ๋๋ณ๋ก ๋ค๋ฅธ ์ธ์คํด์ค๋ฅผ ๋๊ฒจ์ฃผ๊ฒ ํ ์ ์์
import java.util.HashMap;
import java.util.Map;
public class Elvis {
// ์ธ์คํด์ค๋ฅผ ์ ์ฅํ ๋งต
private static final Map<Long, Elvis> instances = new HashMap<>();
// private ์์ฑ์
private Elvis() {
// ์ด๊ธฐํ ์ฝ๋
}
// ์ ์ ๋ฉ์๋: ์ค๋ ๋ ID๋ฅผ ๊ธฐ์ค์ผ๋ก ์ธ์คํด์ค๋ฅผ ๋ฐํ
public static Elvis getInstance() {
long threadId = Thread.currentThread().getId();
return instances.computeIfAbsent(threadId, id -> new Elvis());
}
public void leaveTheBuilding() {
// ํ๋ ๊ตฌํ
}
}- ์ธ์คํด์ค ์ ์ฅ์:
instances๋ผ๋Map์ ์ฌ์ฉํ์ฌ ๊ฐ ์ค๋ ๋์ ๋ํ ์ธ์คํด์ค๋ฅผ ์ ์ฅํ๋ค. ์ค๋ ๋ ID๋ฅผ ํค๋ก ์ฌ์ฉํ๋ค. - ์ ์ ๋ฉ์๋:
getInstance()๋ฉ์๋๋ ํ์ฌ ์ค๋ ๋์ ID๋ฅผ ๊ฐ์ ธ์์, ํด๋น ์ค๋ ๋์ ๋ํ ์ธ์คํด์ค๊ฐ ์ด๋ฏธ ์กด์ฌํ๋์ง ํ์ธํ๋ค. ์กด์ฌํ์ง ์์ผ๋ฉด ์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ ์ ์ฅ - ์ ์ฐ์ฑ: ์ด ๊ตฌํ์ API๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ ๋, ์ฌ์ฉ์๊ฐ ์ํ ๊ฒฝ์ฐ ์ค๋ ๋๋ง๋ค ๋ค๋ฅธ ์ธ์คํด์ค๋ฅผ ๋ฐํํ ์ ์๊ฒ ํ๋ค. ์ฆ, ๊ฐ ์ค๋ ๋๋ ๋
๋ฆฝ์ ์ผ๋ก
Elvis์ธ์คํด์ค๋ฅผ ๊ฐ์ง ์ ์๋ค.
- ์ํ๋ค๋ฉด ์ ์ ํฉํฐ๋ฆฌ๋ฅผ
์ ๋ค๋ฆญ ์ฑ๊ธํด ํฉํฐ๋ฆฌ๋ก ๋ง๋ค ์ ์๋ค. : ์ ์ ํฉํฐ๋ฆฌ์ ๋ฉ์๋ ์ฐธ์กฐ๋ฅผ๊ณต๊ธ์(supplier)๋ก ์ฌ์ฉํ ์ ์๋ค๋ ์ ์ด๋ค.
import java.util.function.Supplier;
public class Elvis {
private static final Map<Long, Elvis> instances = new HashMap<>();
private Elvis() {
// ์ด๊ธฐํ ์ฝ๋
}
public static Elvis getInstance(Supplier<Elvis> supplier) {
long threadId = Thread.currentThread().getId();
return instances.computeIfAbsent(threadId, id -> supplier.get());
}
public void leaveTheBuilding() {
// ํ๋ ๊ตฌํ
}
}
// ์ฌ์ฉ ์์
public class Main {
public static void main(String[] args) {
Elvis elvis = Elvis.getInstance(Elvis::new); // ๊ณต๊ธ์๋ก์์ ๋ฉ์๋ ์ฐธ์กฐ
elvis.leaveTheBuilding();
}
}๐ง ์ฐธ๊ณ ๋ก ์ API๋ฅผ ๋ฐ๊พธ์ง ์๊ณ ๋ ์ฑ๊ธํด์ ๋ณ๊ฒฝํ๋ ๋ฐฉ๋ฒ, API๋ฅผ ๋ฐ๊พธ์ง ์๊ณ ๋ ์ฌ๋ฌ ์ธ์คํด์ค๋ฅผ ๋ฐํํ ์ ์๋๋ก ๋ณ๊ฒฝํ๋ ๊ฒ์ ๊ฒฐ๊ตญ ์ฝ๋๋ฅผ ๋ฐ๊พธ๋ ๊ฑด๋ฐ ์๋ฏธ๊ฐ ์์ด?
AI ๋ต๋ณ
์ข์ ์ง๋ฌธ์ ๋๋ค. "API๋ฅผ ๋ฐ๊พธ์ง ์๊ณ ๋"๋ผ๋ ํํ์ ๊ธฐ์กด ์ธํฐํ์ด์ค(๋ฉ์๋ ์๊ทธ๋์ฒ ๋ฑ)๋ฅผ ์ ์งํ๋ฉด์ ๋ด๋ถ ๊ตฌํ์ ๋ณ๊ฒฝํ ์ ์๋ค๋ ์๋ฏธ์ ๋๋ค. ์ฆ, ์ธ๋ถ์์ ์ฌ์ฉํ๋ ์ฝ๋์ ์ํฅ์ ์ฃผ์ง ์๊ณ , ํด๋์ค์ ๋์ ๋ฐฉ์์ ๋ฐ๊ฟ ์ ์๋ค๋ ์ ์์ ์๋ฏธ๊ฐ ์์ต๋๋ค.
- ํธํ์ฑ ์ ์ง: ๊ธฐ์กด ์ฝ๋๋ฅผ ์ฌ์ฉํ๋ ๋ค๋ฅธ ๋ถ๋ถ์ ๋ณ๊ฒฝํ ํ์๊ฐ ์์ผ๋ฏ๋ก, ์์คํ
์ ์์ ์ฑ์ ์ ์งํ ์ ์์ต๋๋ค. ์ฆ, ์ธ๋ถ์์
getInstance()ํธ์ถ ๋ฐฉ์์ ๊ทธ๋๋ก ์ ์ง๋ฉ๋๋ค. - ์ ์ฐ์ฑ: ๋ด๋ถ์ ์ผ๋ก ์ค๋ ๋๋ณ ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋ ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝํจ์ผ๋ก์จ, ํ์์ ๋ฐ๋ผ ์ฌ๋ฌ ์ธ์คํด์ค๋ฅผ ์ ๊ณตํ ์ ์์ต๋๋ค. ์ด๋ ์๋ก์ด ์๊ตฌ์ฌํญ์ด ์๊ธธ ๋ ์ ์ฉํฉ๋๋ค.
- ํ์ฅ์ฑ: ๋์ค์ ๋ ๋ณต์กํ ๋ก์ง์ด๋ ์ํ ๊ด๋ฆฌ๊ฐ ํ์ํ ๋, API๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ ๋ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๊ฑฐ๋ ์์ ํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, ๊ธฐ์กด์ Elvis.getInstance()๋ฅผ ์ฌ์ฉํ๋ ์ฝ๋๊ฐ ์๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค. ์ด ์ฝ๋๋ ๋ณ๊ฒฝํ์ง ์๊ณ ๋, ๋ด๋ถ ๊ตฌํ์ ํตํด ์ค๋ ๋๋ณ๋ก ๋ค๋ฅธ ์ธ์คํด์ค๋ฅผ ๊ด๋ฆฌํ๊ฒ ํ ์ ์์ต๋๋ค.
Elvis elvis1 = Elvis.getInstance();
Elvis elvis2 = Elvis.getInstance();์ ์ฝ๋๋ ์ฌ์ ํ ๋์ผํ๊ฒ ์๋ํ์ง๋ง, ๋ด๋ถ ๊ตฌํ์์๋ ์ด์ ๊ฐ ์ค๋ ๋์ ๋ํด ๋ค๋ฅธ Elvis ์ธ์คํด์ค๋ฅผ ์ ๊ณตํ๊ฒ ๋ฉ๋๋ค. ์ธ๋ถ ์ฝ๋๋ ์ ํ ๋ณ๊ฒฝ๋์ง ์์ง๋ง, ๋ด๋ถ ๋์์ ํจ์ฌ ๋ ์ ์ฐํด์ง ๊ฒ์
๋๋ค.
๊ฒฐ๋ก ์ ์ผ๋ก, API๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ ๋ ๋ด๋ถ ๊ตฌํ์ ์์ ํ๋ ๊ฒ์ ์ฝ๋์ ์ ์ฐ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ๋์ด๋ ์ข์ ๋ฐฉ๋ฒ์ ๋๋ค. ์ด๋ ์ฅ๊ธฐ์ ์ผ๋ก ์์คํ ์ ํ์ฅ์ฑ๊ณผ ์์ ์ฑ์ ๋ณด์ฅํ๋ ๋ฐ ํฐ ๋์์ด ๋ฉ๋๋ค.
-
๋ฉ๋ชจ๋ฆฌ ์ฃผ์๊ฐ ๋๊ฐ์ ํ ๊ฐ์ ์ธ์คํด์ค๋ง ์์ด์ผ ํ๋๋ฐ ์ง๋ ฌํ ํ ์ญ์ง๋ ฌํ๋ฅผ ํ๊ฒ ๋๋ฉด, ์์ ๋ค๋ฅธ ์ธ์คํด์ค๊ฐ ์์ฑ๋๊ฒ ๋๋ฒ๋ฆฌ๋ ๊ฑฐ์
-
Serializable ๊ตฌํ: ์ฑ๊ธํด ํด๋์ค๋ฅผ ์ง๋ ฌํํ๋ ค๋ฉด
Serializable์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํด์ผ ํ๋ค. ๊ทธ๋ฌ๋ ์ด ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ ๊ฒ๋ง์ผ๋ก๋ ์ถฉ๋ถํ์ง ์๋ค. -
transient ํ๋: ๋ชจ๋ ์ธ์คํด์ค ํ๋๋ฅผ
transient๋ก ์ ์ธํด์ผ ํ๋ฉฐ, ์ด๋ ์ง๋ ฌํ ์ ํด๋น ํ๋๊ฐ ์ ์ฅ๋์ง ์๋๋ก ํ๋ค. -
readResolve ๋ฉ์๋: ์ง๋ ฌํ๋ ๊ฐ์ฒด๋ฅผ ์ญ์ง๋ ฌํํ ๋๋ง๋ค ์๋ก์ด ์ธ์คํด์ค๊ฐ ์์ฑ๋๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํด
readResolve๋ฉ์๋๋ฅผ ์ ๊ณตํ๋ค. ์ด ๋ฉ์๋๋ ์ญ์ง๋ ฌํ ๊ณผ์ ์์ ํธ์ถ๋์ด, ์ง์ง ์ฑ๊ธํด ์ธ์คํด์ค๋ฅผ ๋ฐํํ๊ฒ ๋๋ค.//์ฑ๊ธํด์์ ๋ณด์ฅํด์ฃผ๋ readResolve ๋ฉ์๋ private Object readResolve() { return INSTANCE; // ์ง์ง Elvis ์ธ์คํด์ค๋ฅผ ๋ฐํ ๊ฐ์ง Elvis๋ ๊ฐ๋น์ง ์ปฌ๋ ํฐ์๊ฒ }
์ด ๋ฉ์๋๋ ๊ฐ์ง
Elvis์ธ์คํด์ค๊ฐ ์์ฑ๋๋ ๊ฒ์ ๋ฐฉ์งํ๊ณ , ๊ธฐ์กด์INSTANCE๋ฅผ ๋ฐํํ์ฌ ์๋์ ์ฑ๊ธํด์ ์ ์งํ๋ค. ํน์ ํด๋์ค์์ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ์ง๋ ฌํ์ ์ญ์ง๋ ฌํ๋ฅผ ์ง์ํ๋ ํด๋์ค์์readResolve๋ฉ์๋๋ฅผ ์ ์ํ๋ฉด, ํด๋น ํด๋์ค์ ์ธ์คํด์ค๊ฐ ์ญ์ง๋ ฌํ๋ ๋ ํธ์ถ๋๋ค.
โ๏ธ "์ง์ง Elvis ์ธ์คํด์ค๋ฅผ ๋ฐํํ๊ณ ๊ฐ์ง Elvis๋ ๊ฐ๋น์ง ์ปฌ๋ ํฐ์๊ฒ"๋ผ๋ ํํ
์ฃผ๋ก ์ฑ๊ธํด ํจํด์ ์ค๋ช ํ ๋ ์ฌ์ฉ๋๋ค. ์ฌ๊ธฐ์ "์ง์ง Elvis"๋ ์ค์ ๋ก ์ฌ์ฉํด์ผ ํ๋ ์ ์ผํ ์ธ์คํด์ค๋ฅผ ์๋ฏธํ๊ณ , "๊ฐ์ง Elvis"๋ ๋ถํ์ํ๊ฒ ์์ฑ๋ ์ธ์คํด์ค๋ฅผ ์๋ฏธํฉ
์ด ๋ฌธ๊ตฌ๋
readResolve๋ฉ์๋์ ์ญํ ์ ๊ฐ์กฐํ๋ค. ์ญ์ง๋ ฌํ ๊ณผ์ ์์readResolve๋ฉ์๋๊ฐ ํธ์ถ๋๋ฉด, ๊ฐ์ง ์ธ์คํด์ค๊ฐ ์๋ ์ง์ง ์ธ์คํด์ค๋ฅผ ๋ฐํํ์ฌ, ๋ถํ์ํ ์ธ์คํด์ค๊ฐ ์์ฑ๋๋ ๊ฒ์ ๋ฐฉ์งํ๋ค. ๊ฐ์ง ์ธ์คํด์ค๋ ๋ ์ด์ ํ์ ์๊ฒ ๋์ด ๊ฐ๋น์ง ์ปฌ๋ ํฐ์ ์ํด ์๊ฑฐ๋ ์ ์๋ค. ์ฆ, ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ์ธก๋ฉด์์ ๋ถํ์ํ ๊ฐ์ฒด๋ฅผ ์ ๊ฑฐํ์ฌ ์์์ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๊ฒ ๋๋ค.
-
์ด๊ฑฐ ํ์ : ์ฑ๊ธํด์ ๊ตฌํํ๋ ์ธ ๋ฒ์งธ ๋ฐฉ๋ฒ์ผ๋ก, ์์๊ฐ ํ๋์ธ ์ด๊ฑฐ ํ์ ์ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค. ์๋์ ๊ฐ์ด ์ ์ธํ ์ ์์ต๋๋ค.
public enum Elvis { INSTANCE; public void leaveTheBuilding() { // ๋ฉ์๋ ๊ตฌํ }}
-
์ฅ์ :
- ๊ฐ๊ฒฐํจ: ์ฝ๋๊ฐ ๋ ๊ฐ๋จํ๊ณ ์ดํดํ๊ธฐ ์ฌ์์ง
- ์ง๋ ฌํ: ์ถ๊ฐ์ ์ธ ๋ ธ๋ ฅ ์์ด ์๋์ผ๋ก ์ง๋ ฌํ๊ฐ ๊ฐ๋ฅํ๋ฉฐ, ๋ณต์กํ ์ง๋ ฌํ ์ํฉ์์๋ ์์
- ๋ฆฌํ๋ ์ ๊ณต๊ฒฉ ๋ฐฉ์ง: ๋ฆฌํ๋ ์ ์ ํตํด ์๋ก์ด ์ธ์คํด์ค๊ฐ ์์ฑ๋๋ ๊ฒ์ ๋ฐฉ์งํ๋ฉฐ, ์ด๊ฑฐ ํ์ ์ ์๋ฐ์์ ์ฑ๊ธํด ํจํด์ ์์ ํ๊ฒ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ผ๋ก ๋๋ฆฌ ๊ถ๋๋ค.
-
์ ํ์ฌํญ: ์ด๊ฑฐ ํ์ ์ ๋ค๋ฅธ ํด๋์ค๋ฅผ ์์ํ ์ ์๊ธฐ ๋๋ฌธ์, ์ฑ๊ธํด์ด ๋ค๋ฅธ ํด๋์ค๋ฅผ ์์ํด์ผ ํ ๊ฒฝ์ฐ์๋ ์ฌ์ฉํ ์ ์๋ค. ๊ทธ๋ฌ๋ ์ด๊ฑฐ ํ์ ์ ๋ค๋ฅธ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ์ ์๋ค.
๊ฒฐ๋ก ์ ์ผ๋ก, readResolve ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ง๋ ฌํ ์ ์ง์ง ์ธ์คํด์ค๋ฅผ ๋ฐํํจ์ผ๋ก์จ ์ฑ๊ธํด์ ๋ณด์ฅํ๊ณ , ์์๊ฐ ํ๋์ธ ์ด๊ฑฐ ํ์
์ ์ฌ์ฉํ์ฌ ๊ฐ๊ฒฐํ๊ณ ์์ ํ๊ฒ ์ฑ๊ธํด์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ด ์๋ค. ์ด ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ ๊ฐ๊ฐ์ ์ํฉ์ ๋ง๊ฒ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ํนํ ์ด๊ฑฐ ํ์
์ ๋ณต์กํ ์ง๋ ฌํ์ ๋ฆฌํ๋ ์
๊ณต๊ฒฉ์ ๋ํ ์์ ์ฑ์ ์ ๊ณตํ๋ ์ต์ ์ ์ ํ์ผ๋ก ์ฌ๊ฒจ์ง๋ค.
++ ์คํฐ๋์ ์ถ๊ฐ
class Singleton {
// ์ฑ๊ธํค ํด๋์ค ๊ฐ์ฒด๋ฅผ ๋ด์ ์ธ์คํด์ค ๋ณ์
private static Singleton instance;
// ์์ฑ์๋ฅผ private๋ก ์ ์ธ (์ธ๋ถ์์ new ์ฌ์ฉ X)
private Singleton() {}
// ์ธ๋ถ์์ ์ ์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ๊ทธ์ ์์ผ ์ด๊ธฐํ ์งํ (lazy)
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton(); // ์ค์ง 1๊ฐ์ ๊ฐ์ฒด๋ง ์์ฑ
}
return instance;
}
}์ ๊ณตํ์ Singleton ํด๋์ค๋ ๊ธฐ๋ณธ์ ์ธ ์ฑ๊ธํค ํจํด์ ๊ตฌํํ๊ณ ์์ง๋ง, ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์ ์์ ํ์ง ์์ ๋ฌธ์ ๊ฐ ์๋ค. ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์์ getInstance() ๋ฉ์๋๋ฅผ ํธ์ถํ ๊ฒฝ์ฐ, instance๊ฐ ์ฌ๋ฌ ๋ฒ ์ด๊ธฐํ๋ ์ ์๋ ์ํ์ด ์๋ค.
์ ์ฝ๋์์ ๋ฌธ์
- ์ค๋ ๋๋ ์๋ค๊ณ ํ๋จ์ ํ๊ฒ ๋จ...๊ฒฐ๊ตญ ์ฑ๊ธํค์ ๋ง๋ค๊ธฐ ์ํด ๋ง๋ค์ด์ง ์ฝ๋์ธ๋ฐ. .์ฑ๊ธํค์ด ๊นจ์ง๊ฒ ๋๋ค๋ ๊ฒ
- getInstance์์ ์ธ์คํด์ค๊ฐ ์๋๋ฐ ์ธ์คํด์ค๊ฐ ์์ฑ๋๋ ๊ฑธ ์๋ ์๋ค.
ํด๊ฒฐ๋ฐฉ๋ฒ
๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ getInstance() ๋ฉ์๋์ synchronized ํค์๋๋ฅผ ์ถ๊ฐํ์ฌ ๋๊ธฐํํ๋ ๊ฒ์
๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ํ ๋ฒ์ ํ๋์ ์ค๋ ๋๋ง ๋ฉ์๋์ ์ ๊ทผํ ์ ์์ต๋๋ค.
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}class Singleton {
// ์ฑ๊ธํค ํด๋์ค ๊ฐ์ฒด๋ฅผ ๋ด์ ์ธ์คํด์ค ๋ณ์
private static Singleton instance;
// ์์ฑ์๋ฅผ private๋ก ์ ์ธ (์ธ๋ถ์์ new ์ฌ์ฉ X)
private Singleton() {}
// ์ธ๋ถ์์ ์ ์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ๊ทธ์ ์์ผ ์ด๊ธฐํ ์งํ (lazy)
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton(); // ์ค์ง 1๊ฐ์ ๊ฐ์ฒด๋ง ์์ฑ
}
return instance;
}
}๋งค๋ฒ ๋๊ธฐํํ๋ฉด... ์ฑ๋ฅ ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์์ ๋ชจ๋ ์ค๋ ๋๊ฐ ๋๊ธฐํ๋ฅผ ํ๊ฒ ๋จ..
์ฑ๋ฅ์ ๊ฐ์ ํ๊ธฐ ์ํด ์ด์ค ๊ฒ์ฌ ์ ๊ธ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด ๋ฐฉ๋ฒ์ synchronized ๋ธ๋ก์ ์ต์ํํ์ฌ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค
์ฌ๊ธฐ์ ์ง๋ฌธ?
- if๊ฐ ๋ ๋ฒ ๊ฑธ๋ฆฐ ์ด์ ?
๋๊ธฐํ๋ฅผ ์ ํ์ ์ผ๋ก ํ๊ธฐ ์ํด? ์ฒ์ instance๋ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋๊ธฐ์ํ์ ๊ฑธ๋ฆด ์ ์๋๋ฐ... ๊ทธ ๋ค์ ๋ถํฐ ๋ค์ด์ค๋ ์ค๋ ๋๋ค์ ๋๊ธฐ ์ํ๊ฐ ์๋๊ณ ๋น ๋ฅด๊ฒ ๋์ด๊ฐ ์ ์์ด์..?
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) { //์ต์ ๊ฐ์ผ๋ก ๋๊ธฐํ๊ฐ ๊ฐ๋ฅ
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}class Singleton {
private static volatile Singleton instance; // volatile ํค์๋ ์ ์ฉ
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
// ๋ฉ์๋์ ๋๊ธฐํ ๊ฑฐ๋๊ฒ ์๋, Singleton ํด๋์ค ์์ฒด๋ฅผ ๋๊ธฐํ ๊ฑธ์ด๋ฒ๋ฆผ
synchronized (Singleton.class) {
if(instance == null) {
instance = new Singleton(); // ์ต์ด ์ด๊ธฐํ๋ง ๋๊ธฐํ ์์
์ด ์ผ์ด๋์ ๋ฆฌ์์ค ๋ญ๋น๋ฅผ ์ต์ํ
}
}
}
return instance; // ์ต์ด ์ด๊ธฐํ๊ฐ ๋๋ฉด ์์ผ๋ก ์์ฑ๋ ์ธ์คํด์ค๋ง ๋ฐํ
}
}์ ์ ์ด๊ธฐํ ๋ธ๋ก์ ์ฌ์ฉํ์ฌ ํด๋์ค๊ฐ ๋ก๋๋ ๋ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ๋ ์์ต๋๋ค. ์ด ๋ฐฉ๋ฒ์ ์ค๋ ๋ ์์ ํ๋ฉฐ, ๊ฐ๋จํ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค.
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}class Singleton {
private Singleton() {}
// static ๋ด๋ถ ํด๋์ค๋ฅผ ์ด์ฉ
// Holder๋ก ๋ง๋ค์ด, ํด๋์ค๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ๋ก๋๋์ง ์๊ณ getInstance ๋ฉ์๋๊ฐ ํธ์ถ๋์ด์ผ ๋ก๋๋จ
private static class SingleInstanceHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingleInstanceHolder.INSTANCE;
}
}- ์ฑ๋ฅ ์ด์๊ฐ ์์ด์ ๋ง์ด ์ฌ์ฉํจ
- ๋๊ธฐํ๋ ์๊ธฐ ๋๋ฌธ์ ๋์ ์ง๋ ฌํ๋ ๋ฆฌํ๋ ์ ๊ณต๊ฒฉ์ด ๋ค์ด์ฌ ์ ์๋ค.
Java์์๋ enum์ ์ฌ์ฉํ์ฌ ์ฑ๊ธํค์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ๋ ์์ต๋๋ค. ์ด ๋ฐฉ๋ฒ์ ์ง๋ ฌํ์ ๋ฆฌํ๋ ์
๊ณต๊ฒฉ์ ๋ํด ์์ ํฉ๋๋ค.
public enum Singleton {
INSTANCE;
// ํ์ํ ๋ฉ์๋ ์ถ๊ฐ
public void someMethod() {
// ...
}
}๋ฆฌํ๋ ์ ๊น์ง ๋ฐฉ์ดํ ๊ฒ
import java.io.ObjectStreamException;
import java.io.Serializable;
public class Singleton implements Serializable {
// ์ง๋ ฌํ ๋ฐฉ์ง๋ฅผ ์ํด serialVersionUID๋ฅผ ๋ช
์์ ์ผ๋ก ์ ์ธ
private static final long serialVersionUID = 1L;
// ์์ฑ์์์ ์ด๋ฏธ ๊ฐ์ฒด๊ฐ ์์ฑ๋ ๊ฒฝ์ฐ ์์ธ๋ฅผ ๋์ ธ Reflection์ ํตํ ์ถ๊ฐ ์ธ์คํด์ค ์์ฑ์ ๋ฐฉ์ง
private Singleton() {
if (SingleInstanceHolder.INSTANCE != null) {
throw new IllegalStateException("Singleton instance already created.");
}
}
// static ๋ด๋ถ ํด๋์ค๋ฅผ ์ด์ฉํ Singleton ๊ตฌํ
private static class SingleInstanceHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingleInstanceHolder.INSTANCE;
}
// ์ญ์ง๋ ฌํ ์ Singleton ๋ณด์ฅ (๊ธฐ์กด ์ธ์คํด์ค๋ฅผ ๋ฐํ)
private Object readResolve() throws ObjectStreamException {
return SingleInstanceHolder.INSTANCE;
}
}