# Singleton Pattern 페베로 오닐(Feverro O’Neal)은 UI 스타일이 너무 다양하다고 불평한다. 어플리케이션의 UI 설정에 하나의 스타일만 쓰도록 하자. 페드로: 하지만 잠깐만요, 유저마다 서로 다른 UI 스타일을 저장하라는 요구 사항이 있었죠. 이브: 그 요구사항이 바뀌었어요. 페드로: 오케이, 그러면 설정 사항을 싱글톤에 저장하고 모든 곳에서 싱글톤을 사용하면 돼요. public final class UIConfiguration { public static final UIConfiguration INSTANCE = new UIConfiguration("ui.config"); private String backgroundStyle; private String fontStyle; /* other UI properties */ private UIConfiguration(String configFile) { loadConfig(configFile); } private static void loadConfig(String file) { // process file and fill UI properties INSTANCE.backgroundStyle = "black"; INSTANCE.fontStyle = "Arial"; } public String getBackgroundStyle() { return backgroundStyle; } public String getFontStyle() { return fontStyle; } } 페드로: 저런 식으로 모든 설정 정보가 UI들 사이에서 공유되는 거죠. 이브: 네, 하지만…​ 코드가 왜 이리 많죠? 페드로: UIConfiguration의 인스턴스가 오직 하나만 존재하도록 보장한거죠. 이브: 물어볼 게 있어요. 싱글톤과 전역변수의 차이가 뭐죠? 페드로: 뭐라구요? 이브: …​싱글톤과 전역 변수의 차이요. 페드로: 자바는 전역변수를 지원하지 않아요. 이브: 하지만 UIConfiguration.INSTANCE는 전역변수에요. 페드로: 글쎄요, 비슷하긴 하죠. 이브: 저 자바 코드는 클로저에서는 그냥 단지 [[def]]일 뿐이죠. (def ui-config (load-config "ui.config")) (defn load-config [config-file] ;; process config file and return map with configuratios {:bg-style "black" :font-style "Arial"}) 페드로: 하지만, 스타일을 어떻게 바꾸죠? 이브: 자바에서 하는 것과 똑같은 방식으로요. 페드로: 음…​ 오케이, 살짝 바꿔볼게요. UIConfiguration.loadConfig를 public으로 만들고, 설정이 바뀔 때 이 메소드를 호출하는 거죠. 이브: 그러면 ui-config를 아톰[[atom]]으로 하고, 설정이 바뀌면 [[swap!]]을 호출하면 돼요. 페드로: 하지만 아톰은 병행 프로그래밍 상황에서만 유용하잖아요. 이브: 맞아요, 유용하죠. 하지만 병행 프로그래밍 상황에만 그런 건 아니에요. 그리고 아톰을 읽는 것은 생각만큼 느리지 않아요. 마지막으로 아톰은 UI 설정을 원자적으로 바꾸죠. 페드로: 저런 단순한 예제에 사용하기에는 아톰이 좀 과분해 보이네요. 이브: 아니요, 그렇지 않아요. 아톰처럼 원자적으로 변경하지 않으면, UI 설정이 바뀔 때 랜더러들이 backgroundStyle는 바뀐 값으로, fontStyle은 이전 값 으로 읽을 가능성이 있어요. 페드로: 그러면, loadConfig에 synchronized를 사용하면 돼요. 이브: 그렇게 되면 getter들에도 synchonized를 사용해야 하는데, 그러면 느려지죠. 페드로: Double-Checked Locking 이디엄을 쓰면 돼요. 이브: Double-Checked Locking은 좋은 방법이긴 하지만, 원자성을 완벽하게 보장해 주지는 않죠. 페드로: 오케이, 포기, 당신이 이겼어요.