Skip to content

Latest commit

ย 

History

History
413 lines (298 loc) ยท 18 KB

File metadata and controls

413 lines (298 loc) ยท 18 KB

item 03 : private ์ƒ์„ฑ์ž๋‚˜ ์—ด๊ฑฐ ํƒ€์ž…์œผ๋กœ ์‹ฑ๊ธ€ํ„ด์ž„์„ ๋ณด์ฆํ•˜๋ผ.

์‹ฑ๊ธ€ํ„ด์ž„์„ ๋ณด์ฆํ•˜๋ผ

์‹ฑ๊ธ€ํ„ด(singleton)์ด๋ž€?

  • ์ธ์Šคํ„ด์Šค๋ฅผ ์˜ค์ง ํ•˜๋‚˜๋งŒ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ํด๋ž˜์Šค๋ฅผ ๋งํ•œ๋‹ค.
  • ์ „ํ˜•์ ์ธ ์˜ˆ๋กœ๋Š” ํ•จ์ˆ˜์™€ ๊ฐ™์€ ๋ฌด์ƒํƒœ(stateless) ๊ฐ์ฒด๋‚˜ ์„ค๊ณ„์ƒ ์œ ์ผํ•ด์•ผ ํ•˜๋Š” ์‹œ์Šคํ…œ ์ปดํฌ๋„ŒํŠธ

ํด๋ž˜์Šค๋ฅผ ์‹ฑ๊ธ€ํ„ด์œผ๋กœ ๋งŒ๋“ค๋ฉด ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ๋ฅผ ํ…Œ์ŠคํŠธํ•˜๊ธฐ๊ฐ€ ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ๋‹ค.

์ด์œ ๋Š” ํƒ€์ž…์„ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ •์˜ํ•œ ๋‹ค์Œ ๊ทธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์„œ ๋งŒ๋“  ์‹ฑ๊ธ€ํ„ด์ด ์•„๋‹ˆ๋ผ๋ฉด ์‹ฑ๊ธ€ํ„ด ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์งœ(MOCK) ๊ตฌํ˜„์œผ๋กœ ๋Œ€์ฒดํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์‹ฑ๊ธ€ํ„ด์„ ๋งŒ๋“œ๋Š” ๋ฐฉ์‹

๋‘ ๋ฐฉ์‹ ๋ชจ๋‘ ์ƒ์„ฑ์ž๋Š” private์œผ๋กœ ๊ฐ์ถฐ๋‘๊ณ , ์œ ์ผํ•œ ์ธ์Šคํ„ด์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜๋‹จ์œผ๋กœ public static ๋ฉค๋ฒ„๋ฅผ ํ•˜๋‚˜ ๋งˆ๋ จ

๋ฐฉ์‹ 1 : publioc static ๋ฉค๋ฒ„๊ฐ€ final ํ•„๋“œ์ธ ๋ฐฉ์‹

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์ด๋‹ˆ ์ ˆ๋Œ€๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์—†๋‹ค.
  • ๊ฐ„๊ฒฐํ•˜๋‹ค.

๋ฐฉ์‹ 2 : ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ public static ๋ฉค๋ฒ„๋กœ ์ œ๊ณต

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() {
        // ํ–‰๋™ ๊ตฌํ˜„
    }
}
  1. ์ธ์Šคํ„ด์Šค ์ €์žฅ์†Œ: instances๋ผ๋Š” Map์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ ์Šค๋ ˆ๋“œ์— ๋Œ€ํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ์ €์žฅํ•œ๋‹ค. ์Šค๋ ˆ๋“œ ID๋ฅผ ํ‚ค๋กœ ์‚ฌ์šฉํ•œ๋‹ค.
  2. ์ •์  ๋ฉ”์„œ๋“œ: getInstance() ๋ฉ”์„œ๋“œ๋Š” ํ˜„์žฌ ์Šค๋ ˆ๋“œ์˜ ID๋ฅผ ๊ฐ€์ ธ์™€์„œ, ํ•ด๋‹น ์Šค๋ ˆ๋“œ์— ๋Œ€ํ•œ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ด๋ฏธ ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค. ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ์ƒˆ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ €์žฅ
  3. ์œ ์—ฐ์„ฑ: ์ด ๊ตฌํ˜„์€ 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๋ฅผ ๋ฐ”๊พธ์ง€ ์•Š๊ณ ๋„"๋ผ๋Š” ํ‘œํ˜„์€ ๊ธฐ์กด ์ธํ„ฐํŽ˜์ด์Šค(๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜ ๋“ฑ)๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ๋‚ด๋ถ€ ๊ตฌํ˜„์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. ์ฆ‰, ์™ธ๋ถ€์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๊ณ , ํด๋ž˜์Šค์˜ ๋™์ž‘ ๋ฐฉ์‹์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์—์„œ ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜๋ฏธ์™€ ์žฅ์ 

  1. ํ˜ธํ™˜์„ฑ ์œ ์ง€: ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ ๋ถ€๋ถ„์€ ๋ณ€๊ฒฝํ•  ํ•„์š”๊ฐ€ ์—†์œผ๋ฏ€๋กœ, ์‹œ์Šคํ…œ์˜ ์•ˆ์ •์„ฑ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์™ธ๋ถ€์—์„œ getInstance() ํ˜ธ์ถœ ๋ฐฉ์‹์€ ๊ทธ๋Œ€๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.
  2. ์œ ์—ฐ์„ฑ: ๋‚ด๋ถ€์ ์œผ๋กœ ์Šค๋ ˆ๋“œ๋ณ„ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ณ€๊ฒฝํ•จ์œผ๋กœ์จ, ํ•„์š”์— ๋”ฐ๋ผ ์—ฌ๋Ÿฌ ์ธ์Šคํ„ด์Šค๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์ƒˆ๋กœ์šด ์š”๊ตฌ์‚ฌํ•ญ์ด ์ƒ๊ธธ ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  3. ํ™•์žฅ์„ฑ: ๋‚˜์ค‘์— ๋” ๋ณต์žกํ•œ ๋กœ์ง์ด๋‚˜ ์ƒํƒœ ๊ด€๋ฆฌ๊ฐ€ ํ•„์š”ํ•  ๋•Œ, API๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ ๋„ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ

์˜ˆ๋ฅผ ๋“ค์–ด, ๊ธฐ์กด์— Elvis.getInstance()๋ฅผ ์‚ฌ์šฉํ•˜๋˜ ์ฝ”๋“œ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ์ฝ”๋“œ๋Š” ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ ๋„, ๋‚ด๋ถ€ ๊ตฌํ˜„์„ ํ†ตํ•ด ์Šค๋ ˆ๋“œ๋ณ„๋กœ ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ด€๋ฆฌํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Elvis elvis1 = Elvis.getInstance();
Elvis elvis2 = Elvis.getInstance();

์œ„ ์ฝ”๋“œ๋Š” ์—ฌ์ „ํžˆ ๋™์ผํ•˜๊ฒŒ ์ž‘๋™ํ•˜์ง€๋งŒ, ๋‚ด๋ถ€ ๊ตฌํ˜„์—์„œ๋Š” ์ด์ œ ๊ฐ ์Šค๋ ˆ๋“œ์— ๋Œ€ํ•ด ๋‹ค๋ฅธ Elvis ์ธ์Šคํ„ด์Šค๋ฅผ ์ œ๊ณตํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์™ธ๋ถ€ ์ฝ”๋“œ๋Š” ์ „ํ˜€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์ง€๋งŒ, ๋‚ด๋ถ€ ๋™์ž‘์€ ํ›จ์”ฌ ๋” ์œ ์—ฐํ•ด์ง„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

๊ฒฐ๋ก ์ ์œผ๋กœ, API๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ ๋„ ๋‚ด๋ถ€ ๊ตฌํ˜„์„ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์€ ์ฝ”๋“œ์˜ ์œ ์—ฐ์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ๋†’์ด๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ด๋Š” ์žฅ๊ธฐ์ ์œผ๋กœ ์‹œ์Šคํ…œ์˜ ํ™•์žฅ์„ฑ๊ณผ ์•ˆ์ •์„ฑ์„ ๋ณด์žฅํ•˜๋Š” ๋ฐ ํฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

์‹ฑ๊ธ€ํ„ด(Singleton) ํŒจํ„ด์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ์ง๋ ฌํ™”(Serialization) ๋ฌธ์ œ

1. ์ง๋ ฌํ™”์™€ ์‹ฑ๊ธ€ํ„ด

  • ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๊ฐ€ ๋˜‘๊ฐ™์€ ํ•œ ๊ฐœ์˜ ์ธ์Šคํ„ด์Šค๋งŒ ์žˆ์–ด์•ผ ํ•˜๋Š”๋ฐ ์ง๋ ฌํ™” ํ›„ ์—ญ์ง๋ ฌํ™”๋ฅผ ํ•˜๊ฒŒ ๋˜๋ฉด, ์™„์ „ ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋˜๊ฒŒ ๋˜๋ฒ„๋ฆฌ๋Š” ๊ฑฐ์ž„

  • Serializable ๊ตฌํ˜„: ์‹ฑ๊ธ€ํ„ด ํด๋ž˜์Šค๋ฅผ ์ง๋ ฌํ™”ํ•˜๋ ค๋ฉด Serializable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋Š” ์ถฉ๋ถ„ํ•˜์ง€ ์•Š๋‹ค.

  • transient ํ•„๋“œ: ๋ชจ๋“  ์ธ์Šคํ„ด์Šค ํ•„๋“œ๋ฅผ transient๋กœ ์„ ์–ธํ•ด์•ผ ํ•˜๋ฉฐ, ์ด๋Š” ์ง๋ ฌํ™” ์‹œ ํ•ด๋‹น ํ•„๋“œ๊ฐ€ ์ €์žฅ๋˜์ง€ ์•Š๋„๋ก ํ•œ๋‹ค.

  • readResolve ๋ฉ”์„œ๋“œ: ์ง๋ ฌํ™”๋œ ๊ฐ์ฒด๋ฅผ ์—ญ์ง๋ ฌํ™”ํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด readResolve ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ์—ญ์ง๋ ฌํ™” ๊ณผ์ •์—์„œ ํ˜ธ์ถœ๋˜์–ด, ์ง„์งœ ์‹ฑ๊ธ€ํ„ด ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋œ๋‹ค.

    //์‹ฑ๊ธ€ํ„ด์ž„์„ ๋ณด์žฅํ•ด์ฃผ๋Š” readResolve ๋ฉ”์„œ๋“œ
    private Object readResolve() {    
        return INSTANCE; // ์ง„์งœ Elvis ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ ๊ฐ€์งœ Elvis๋Š” ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ์—๊ฒŒ 
    }

    ์ด ๋ฉ”์„œ๋“œ๋Š” ๊ฐ€์งœ Elvis ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ณ , ๊ธฐ์กด์˜ INSTANCE๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ ์›๋ž˜์˜ ์‹ฑ๊ธ€ํ„ด์„ ์œ ์ง€ํ•œ๋‹ค. ํŠน์ • ํด๋ž˜์Šค์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ง๋ ฌํ™”์™€ ์—ญ์ง๋ ฌํ™”๋ฅผ ์ง€์›ํ•˜๋Š” ํด๋ž˜์Šค์—์„œ readResolve ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜๋ฉด, ํ•ด๋‹น ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์—ญ์ง๋ ฌํ™”๋  ๋•Œ ํ˜ธ์ถœ๋œ๋‹ค.

โœ”๏ธ "์ง„์งœ Elvis ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ๊ฐ€์งœ Elvis๋Š” ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ์—๊ฒŒ"๋ผ๋Š” ํ‘œํ˜„

์ฃผ๋กœ ์‹ฑ๊ธ€ํ„ด ํŒจํ„ด์„ ์„ค๋ช…ํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค. ์—ฌ๊ธฐ์„œ "์ง„์งœ Elvis"๋Š” ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์œ ์ผํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ์˜๋ฏธํ•˜๊ณ , "๊ฐ€์งœ Elvis"๋Š” ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์ƒ์„ฑ๋œ ์ธ์Šคํ„ด์Šค๋ฅผ ์˜๋ฏธํ•ฉ

์ด ๋ฌธ๊ตฌ๋Š” readResolve ๋ฉ”์„œ๋“œ์˜ ์—ญํ• ์„ ๊ฐ•์กฐํ•œ๋‹ค. ์—ญ์ง๋ ฌํ™” ๊ณผ์ •์—์„œ readResolve ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด, ๊ฐ€์งœ ์ธ์Šคํ„ด์Šค๊ฐ€ ์•„๋‹Œ ์ง„์งœ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ, ๋ถˆํ•„์š”ํ•œ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•œ๋‹ค. ๊ฐ€์งœ ์ธ์Šคํ„ด์Šค๋Š” ๋” ์ด์ƒ ํ•„์š” ์—†๊ฒŒ ๋˜์–ด ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํ„ฐ์— ์˜ํ•ด ์ˆ˜๊ฑฐ๋  ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰, ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ์ธก๋ฉด์—์„œ ๋ถˆํ•„์š”ํ•œ ๊ฐ์ฒด๋ฅผ ์ œ๊ฑฐํ•˜์—ฌ ์ž์›์„ ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

2. ์—ด๊ฑฐ ํƒ€์ž…์„ ์ด์šฉํ•œ ์‹ฑ๊ธ€ํ„ด

  • ์—ด๊ฑฐ ํƒ€์ž…: ์‹ฑ๊ธ€ํ„ด์„ ๊ตฌํ˜„ํ•˜๋Š” ์„ธ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์œผ๋กœ, ์›์†Œ๊ฐ€ ํ•˜๋‚˜์ธ ์—ด๊ฑฐ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์ด ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    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๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ์ดˆ๊ธฐํ™”๋  ์ˆ˜ ์žˆ๋Š” ์œ„ํ—˜์ด ์žˆ๋‹ค.

์ € ์ฝ”๋“œ์—์„œ ๋ฌธ์ œ

  1. ์Šค๋ ˆ๋“œ๋Š” ์—†๋‹ค๊ณ  ํŒ๋‹จ์„ ํ•˜๊ฒŒ ๋จ...๊ฒฐ๊ตญ ์‹ฑ๊ธ€ํ†ค์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ ์ฝ”๋“œ์ธ๋ฐ. .์‹ฑ๊ธ€ํ†ค์ด ๊นจ์ง€๊ฒŒ ๋œ๋‹ค๋Š” ๊ฒƒ
  2. getInstance์—์„œ ์ธ์Šคํ„ด์Šค๊ฐ€ ์—†๋Š”๋ฐ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ๊ฑธ ์ˆ˜๋„ ์žˆ๋‹ค.

ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

1. ๋™๊ธฐํ™”(Synchronized) ์‚ฌ์šฉ

๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์€ 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;
    }
}

๋งค๋ฒˆ ๋™๊ธฐํ™”ํ•˜๋ฉด... ์„ฑ๋Šฅ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ์Œ ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ๋™๊ธฐํ™”๋ฅผ ํ•˜๊ฒŒ ๋จ..

2. ์ด์ค‘ ๊ฒ€์‚ฌ ์ž ๊ธˆ(Double-Checked Locking)

์„ฑ๋Šฅ์„ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด ์ด์ค‘ ๊ฒ€์‚ฌ ์ž ๊ธˆ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ 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; // ์ตœ์ดˆ ์ดˆ๊ธฐํ™”๊ฐ€ ๋˜๋ฉด ์•ž์œผ๋กœ ์ƒ์„ฑ๋œ ์ธ์Šคํ„ด์Šค๋งŒ ๋ฐ˜ํ™˜
    }
}

3. ์ •์  ์ดˆ๊ธฐํ™”(Static Initialization)

์ •์  ์ดˆ๊ธฐํ™” ๋ธ”๋ก์„ ์‚ฌ์šฉํ•˜์—ฌ ํด๋ž˜์Šค๊ฐ€ ๋กœ๋“œ๋  ๋•Œ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ ์Šค๋ ˆ๋“œ ์•ˆ์ „ํ•˜๋ฉฐ, ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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;
    }
}
  • ์„ฑ๋Šฅ ์ด์Šˆ๊ฐ€ ์—†์–ด์„œ ๋งŽ์ด ์‚ฌ์šฉํ•จ
  • ๋™๊ธฐํ™”๋„ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋Œ€์‹  ์ง๋ ฌํ™”๋‚˜ ๋ฆฌํ”Œ๋ ‰์…˜ ๊ณต๊ฒฉ์ด ๋“ค์–ด์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

4. Enum์„ ์‚ฌ์šฉํ•œ ์‹ฑ๊ธ€ํ†ค

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;
    }
}