design patterns : singleton
This commit is contained in:
BIN
design-pattern/gof/settings.obj
Normal file
BIN
design-pattern/gof/settings.obj
Normal file
Binary file not shown.
53
design-pattern/gof/src/singleton/App.java
Normal file
53
design-pattern/gof/src/singleton/App.java
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package singleton;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
|
||||||
|
public class App {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
|
||||||
|
Settings instance = Settings.getInstance();
|
||||||
|
Settings instance1 = Settings.getInstance();
|
||||||
|
System.out.println(instance == instance1);
|
||||||
|
|
||||||
|
// 싱글톤 패턴 구현 방법을 깨트리는 방법
|
||||||
|
|
||||||
|
// 1. reflection
|
||||||
|
Constructor<Settings> constructor = Settings.class.getDeclaredConstructor();
|
||||||
|
constructor.setAccessible(true);
|
||||||
|
Settings instance2 = constructor.newInstance();
|
||||||
|
System.out.println(instance == instance2);
|
||||||
|
|
||||||
|
// 2. 직렬화, 역직렬화 (readResolve()로 해결)
|
||||||
|
Settings instance3 = null;
|
||||||
|
try (ObjectOutput out = new ObjectOutputStream(new FileOutputStream("settings.obj"))) {
|
||||||
|
out.writeObject(instance);
|
||||||
|
}
|
||||||
|
try (ObjectInput in = new ObjectInputStream(new FileInputStream("settings.obj"))) {
|
||||||
|
instance3 = (Settings) in.readObject();
|
||||||
|
}
|
||||||
|
System.out.println(instance == instance3);
|
||||||
|
|
||||||
|
|
||||||
|
SettingsEnum instance4 = SettingsEnum.INSTANCE;
|
||||||
|
|
||||||
|
// enum 타입은 reflection 으로 생성 불가
|
||||||
|
SettingsEnum instance5 = null;
|
||||||
|
// Constructor<?>[] declaredConstructors = SettingsEnum.class.getDeclaredConstructors();
|
||||||
|
// for (Constructor<?> declaredConstructor : declaredConstructors) {
|
||||||
|
// declaredConstructor.setAccessible(true);
|
||||||
|
// instance5 = (SettingsEnum) declaredConstructor.newInstance("INSTANCE");
|
||||||
|
// }
|
||||||
|
// System.out.println(instance4 == instance5);
|
||||||
|
|
||||||
|
SettingsEnum instance6 = null;
|
||||||
|
try (ObjectOutput out = new ObjectOutputStream(new FileOutputStream("settings.obj"))) {
|
||||||
|
out.writeObject(instance4);
|
||||||
|
}
|
||||||
|
try (ObjectInput in = new ObjectInputStream(new FileInputStream("settings.obj"))) {
|
||||||
|
instance6 = (SettingsEnum) in.readObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(instance4 == instance6);
|
||||||
|
}
|
||||||
|
}
|
||||||
78
design-pattern/gof/src/singleton/Settings.java
Normal file
78
design-pattern/gof/src/singleton/Settings.java
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package singleton;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class Settings implements Serializable { // 직렬화
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread Safe 하게 Singleton 구현하기
|
||||||
|
* 1. synchronized 키워드 사용
|
||||||
|
* 매번 동기화 과정에서 리소스를 사용하므로 성능저하의 원인이 될 수 있다.
|
||||||
|
*/
|
||||||
|
// private static Settings instance;
|
||||||
|
//
|
||||||
|
// private Settings() {}
|
||||||
|
//
|
||||||
|
// public static synchronized Settings getInstance() {
|
||||||
|
// if (instance == null) {
|
||||||
|
// instance = new Settings();
|
||||||
|
// }
|
||||||
|
// return instance;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread Safe 하게 Singleton 구현하기
|
||||||
|
* 2. 클래스 로딩시 초기화 (eager initialization)
|
||||||
|
* 인스턴스를 만드는 과정이 리소스가 많이 든다면 자주 사용하지 않는 경우 낭비가 될 수 있다.
|
||||||
|
*/
|
||||||
|
// private static final Settings INSTANCE = new Settings();
|
||||||
|
//
|
||||||
|
// private Settings() {}
|
||||||
|
//
|
||||||
|
// public static Settings getInstance() {
|
||||||
|
// return INSTANCE;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread Safe 하게 Singleton 구현하기
|
||||||
|
* 3. double checked locking (java 1.5 이상)
|
||||||
|
* 인스턴스가 있는 경우에는 synchronized 블럭을 사용하지 않기 때문에
|
||||||
|
* 메소드에 synchronized 를 사용한 것과 다르다.
|
||||||
|
*/
|
||||||
|
// private static volatile Settings instance;
|
||||||
|
//
|
||||||
|
// private Settings() {}
|
||||||
|
//
|
||||||
|
// public static Settings getInstance() {
|
||||||
|
// if (instance == null) {
|
||||||
|
// synchronized (Settings.class) {
|
||||||
|
// if (instance == null) {
|
||||||
|
// instance = new Settings();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return instance;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread Safe 하게 Singleton 구현하기
|
||||||
|
* 4. static inner class 사용
|
||||||
|
* SettingsHolder.INSTANCE 가 호출 될 때 인스턴스가 생성 된다. (lazy loading)
|
||||||
|
*/
|
||||||
|
|
||||||
|
private Settings() {}
|
||||||
|
|
||||||
|
private static class SettingsHolder {
|
||||||
|
private static final Settings INSTANCE = new Settings();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Settings getInstance() {
|
||||||
|
return SettingsHolder.INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 역직렬화 시 기본은 인스턴스를 생성하지만 readResolve()가 있으면
|
||||||
|
// 이 메소드를 사용하게 된다.
|
||||||
|
protected Object readResolve() {
|
||||||
|
return getInstance();
|
||||||
|
}
|
||||||
|
}
|
||||||
11
design-pattern/gof/src/singleton/SettingsEnum.java
Normal file
11
design-pattern/gof/src/singleton/SettingsEnum.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package singleton;
|
||||||
|
|
||||||
|
// enum 으로 구현하면 간단하게 해결 가능하다.
|
||||||
|
// enum 은 Serializable 을 상속받고 있다.
|
||||||
|
// eager loading
|
||||||
|
// 상속을 받지 못한다.
|
||||||
|
public enum SettingsEnum {
|
||||||
|
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user