design patterns : singleton

This commit is contained in:
haerong22
2021-11-03 02:34:48 +09:00
parent e60979a162
commit 408593f0b5
142 changed files with 142 additions and 0 deletions

Binary file not shown.

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

View 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();
}
}

View 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