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