2021.11.14_03.싱글톤패턴구현방법을깨트리는방법
본문 바로가기
CS Study/디자인패턴

2021.11.14_03.싱글톤패턴구현방법을깨트리는방법

by KyeongMin 2021. 11. 14.
728x90
반응형
  • 우리가 제대로 만들었지만 사용자가 이상하게 사용하면 깨질 수 있음
public class App{
    
    public static void main(String[] args){
        Settings settings = Settings.getInstance();
        Settings settings1 = Settings.getInstance();
        
       	System.out.println(settings == settings1);
    }
    
    
}
  • 지금은 true인데 이것을 false로 나오는것은
  • 어떻게 선언하냐면 리플렉션을 사용

리플렉션 사용하기

public class App{
    
    public static void main(String[] args) throws NoSuchMethodException{
        Settings settings = Settings.getInstance();
        
        Constructor<Settings> constructor = Settings.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        Settings settings1 = Settings.getInstance();
        
       	System.out.println(settings == settings1);
    }
    
    
}
  • 이 경우 new로 그냥 선언하는것과 비슷하기떄문에 false가 나오게됨

직렬화 & 역 직렬화 사용하기

  • 직렬화
    • 저장할때는 이것
  • 역직렬화
    • 불러올때
public class Settings implements Serializable{
    
    private Settings(){}
    
    private static class SettingsHolder{
		private static final Settings INSTANCE = new Settings();
    }
    
    public static synchronized Settings getInstance(){
        return SettingsHolder.INSTNACE ;
    }
}


public class App{
    
    public static void main(String[] args) throws IOException{
        Settings settings = Settings.getInstance();
        
       try(ObjectOutput out = new ObjectOutPutStreamd(new FileOutPutStream("settings.obj"))){
			out.writeObject(settings);
       }//객체가 파일에 써짐, 직렬화
        
        try(ObjectInput in = new ObjectInputStream(new FileInputStream("settings.obj"))){
			settings1 =(Settings) in.readObject();
        }//역직렬화
        
       	System.out.println(settings == settings1);
    }
    
    
}
  • 객체를 파일로 저장했다가 불러올 수있음
  • 역직렬화를 사용하면 다시 new를 불러와서 사용하기 때문에 다른것이다.
  • 역직렬화 무마 시키는 법은
    • 명시적으로 써있지 않지만
    • 직렬화할때 아래 매소드 사용함
protected Object readResolve(){
}
  • 위에서 원래new를 사용해서 만들어서 다른 인스턴스를 생성되는데

역직렬화 대응 방안

public class Settings implements Serializable{
    
    private Settings(){}
    
    private static class SettingsHolder{
		private static final Settings INSTANCE = new Settings();
    }
    
    public static synchronized Settings getInstance(){
        return SettingsHolder.INSTNACE ;
    }
}
protected Object readResolve(){
	return getInstance();
}
  • 이렇게 선언을 하게되면 해결을 된다.
  • 역직렬화는 대응이 되지만 리플랙션은 대응이 어렵다.

https://github.com/3DPIT/study/blob/master/05.%EC%BD%94%EB%94%A9%EC%9C%BC%EB%A1%9C%ED%95%99%EC%8A%B5%ED%95%98%EB%8A%94GoF%EC%9D%98%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4/01.%EA%B0%9D%EC%B2%B4%EC%83%9D%EC%84%B1%EA%B4%80%EB%A0%A8%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4/2021/11/1114/01.%EC%8B%B1%EA%B8%80%ED%86%A4%ED%8C%A8%ED%84%B4/03.%EC%8B%B1%EA%B8%80%ED%86%A4%ED%8C%A8%ED%84%B4%EA%B5%AC%ED%98%84%EB%B0%A9%EB%B2%95%EC%9D%84%EA%B9%A8%ED%8A%B8%EB%A6%AC%EB%8A%94%EB%B0%A9%EB%B2%95/2021.11.14_03.%EC%8B%B1%EA%B8%80%ED%86%A4%ED%8C%A8%ED%84%B4%EA%B5%AC%ED%98%84%EB%B0%A9%EB%B2%95%EC%9D%84%EA%B9%A8%ED%8A%B8%EB%A6%AC%EB%8A%94%EB%B0%A9%EB%B2%95.md

 

GitHub - 3DPIT/study

Contribute to 3DPIT/study development by creating an account on GitHub.

github.com

 

 

728x90
반응형

댓글