[Java] 싱글톤 디자인 패턴(Singleton Design Pattern) / final 키워드

2022. 10. 5. 14:56Dev.Program/Java & Spring

728x90

책 p251-252

3.4 Singleton 디자인 패턴(JSP 에서 쓰는 MemberBean/DAO 도 디자인패턴임)

⇒ 어떤 목적을 달성하기 위한 프로그래밍 가이드

> 여러개의 인스턴스를 만들면 안될 때(ex) Account() 같이 은행코드들), Singleton 디자인 패턴을 사용함.

< 싱글톤 디자인 패턴(Singleton Design Pattern) >

  • 단 하나의 인스턴스만을 공유하도록 하는 프로그래밍 기법
  • 외부에서 인스턴스 생성을 하지 못하게 차단하고 클래스 내에서 직접 인스턴스를 생성하여 외부에 생성된 인스턴스를 리턴
  • 누구나 단 하나의 인스턴스만을 공유하여 사용해야함

 

< 패턴 규칙 > → 개념 부분 이므로 잘 모르겠으면 밑에 실제 정의할 때의 문법 순서 잘 보기

  1. 외부에서 인스턴스 생성이 불가능하도록 생성자에 private 접근제한자 선언
  2. 자신의 클래스 내에서 인스턴스를 생성하여 참조변수에 저장
    •     ⇒ 외부에서 인스턴스 생성이 불가능하므로
    •     ⇒ 인스턴스 생성없이 접근해야하므로 static 키워드 사용
    •     ⇒ 외부에서 함부로 접근하지 못하도록 private 접근제한자 선언
  3. 생성된 인스턴스를 외부로 리턴하는 Getter 메서드 정의
    •     ⇒ private 접근제한자 멤버변수에 저장된 인스턴스를 리턴
    •     ⇒ 인스턴스 생성없이 접근해야하므로 static 키워드 사용

< 실제 정의할 때의 문법 순서 >

  1. 멤버변수 선언 및 인스턴스 생성(private static)
  2. 생성자 정의(private)
  3. Getter 정의(public static)



======== Ex3.java 만들기

> 생성자에 private 접근지정자 선언

  • 원래 우리가 만들던 생성자(public)

  • public 부분을 private 로 바꿈
  • 그럼 main 안에
    오류남.
  • SingletonClass sc = new SingletonClass(); // 여기가 생성자를 호출하는 코드

  • 이렇게 자신의 클래스에서 직접 인스턴스 생성 가능
  • 그런데, 밖(main 부분)에서 인스턴스 생성을 못하기 때문에 어차피 호출을 못함….!
  • 변수에 접근 할 방법이 없다.
  • 그럴때 필요한 건? Static!! ⇒ 인스턴스 생성 없이도 접근해야하므로 static 키워드 사용
  • 앞에 static 만 붙여줌.

  • main() 에서 sc 를 부르는 방법! (static이기 때문에 클래스명.멤버변수로 부름)
  • 근데 위에서 = null; 이라고 하면 다 날아가기 때문에 저것도 접근제한자를 통해 값을 바꿀 수 없도록 변경해줌.

 

> 이제 여기에 다시 접근하려면!? Getter / Setter (Alt + Shift + S → R)

  • 우린 필요한 Getter만 생성을 해줌. 근데 여기서도 문제가 생김. public 호출하려면 밖에서 인스턴스 생성이 되야하는데 우린 그게 안된다.

  • 그래서 여기도 static 붙여줌!
class SingletonClass {
	
	// 외부에서 생성자 호출이 불가능하도록 private 접근제한자 선언
	private SingletonClass() {}
	
	// 외부에서 인스턴스 생성이 불가능한 대신
      // 자신의 클래스에서 직접 인스턴스 생성
	// ⇒ 인스턴스 생성없이 접근해야하므로 static 키워드 사용
	private static SingletonClass instance = new SingletonClass();
	
	// private 접근제한자가 선언된 멤버변수에 대신 접근하여
	// 생성된 인스턴스를 외부로 리턴하는 Getter 메서드 정의
	public static SingletonClass getInstance() {
		return instance;
	}
} ( ⇒ 나중에 Singleton 패턴 만들라고 해보면 static 을 잘 빼먹습니다! )
  • ⇒ 나중에 Singleton 패턴 만들라고 해보면 static 을 잘 빼먹습니다!
 

  • SingletonClass2 클래스를 만들어서 자동완성 하려니까 오류남(생성할 게 없어서)
  • private SingletonClass2() {} ⇒ 따로 수동으로 적어줌
  • 그 이후에 Getter 는 자동완성으로 해주면 된다(알아서 static 붙음)

  • 메인에서 호출하는 방법.
  • static 메서드인 getInstance() 메서드 호출을 위해 클래스명.메서드(); 로 호출



확인용 > 이제 getInstance() 안에

public void print() {
    System.out.println("print() 메서드 호출!");
}
 
  • 이렇게 print() 메서드를 만들고

> 위(main 안)에서 sc.print(); 로 호출하면 결과값 잘 나온다




p 251-253

< Ex3.java >

⇒ 싱글톤 디자인 패턴 = 싱글톤 패턴이라고도 함! (인스턴스를 한 개만 만들기 위해 쓴다)

  • 출력창
  • 계속 new 를 하면서 새로 만들어준 거라면 두 개가 다르다고 나올텐데, 생성자 한 개를 돌려 쓰니까 같다고 나옴!

 

======== Test3.java 만들기

문제 )

class Account {
	//----------------------------------------------
	// Account 클래스의 싱글톤 디자인 패턴 적용
	>>>>> 여기에 만들기 (안보고 해보기!)	//----------------------------------------------
}
 

답 )

class Account {
	private static Account instance = new Account();
	private Account() {}
	public static Account getInstance() {
		return instance;
	}

      private String bankName = "ITWILL 은행";

	public String getBankName() {
		return bankName;
	} ⇒ 추가

}

 

⇒ 이거 연습 많이 많이 해보기!!!! 그럼 안까먹습니다. (특히 static 적는거 잘 까먹음!)

 

> main에서 호출할 때

public static void main(String[] args) {
	Account ac = Account.getInstance();
	System.out.println(ac.getBankName());
}

====================⇒ 여기까지가 static 은 끝!




교재 p.240 (1) final

변수에 final 이 붙으면 상수라고 생각하면 됨.

< final 키워드 >

  • '변경의 마지막' 이라는 의미로 사용되는 키워드
  • 변수, 메서드, 클래스에 사용 가능
  1. 변수에 final 키워드가 사용될 경우
    • 변수 값 변경 불가 = 상수로 취급됨
    • 반드시 초기화 코드가 포함 되어야 함
    • 초기화 코드를 포함하지 않는 변수를 blank final 변수라고 하며 생성자에서 반드시 해당 변수 초기화가 수행되어야 함!
      • (⇒ 주로 객체마다 다른 고정된 값을 사용해야 하는 경우)
    • 기존 상수(final 변수)를 그대로 사용하는 것은 가능
    • 대표적인 변경 불가 상수 : Math 클래스의 PI 등
    • 상수 선언 시 주로 대문자로 이름을 지정
      • (단어 간의 구분 시 언더스코어(_) 기호 사용. ex) MY_NAME)
  2. 메서드에 final 키워드가 사용될 경우
    • 메서드 내용 변경 불가 = 메서드 오버라이딩 금지
    • 슈퍼클래스의 메서드를 상속받아 그대로 사용하는 것은 가능
  3. 클래스에 final 키워드가 사용될 경우
    • 클래스 내용 변경 불가 = 상속 금지
    • 해당 클래스의 인스턴스 생성을 통해 그대로 사용하는 것은 가능
    • 대표적인 상속 불가 클래스 : String 등



======== Ex4.java 만들기

1. 변수에 final 키워드가 사용될 경우

  • 이렇게는 아무 오류 없이 잘 실행된다. (우리가 평소에 내내 하던 것)

  • class FinalVariable {} 안에 int b를 final int b로 바꿔줌 (final을 붙여줌)

  • 위에 컴파일 에러 발생! final 변수(= 상수)는 값 변경이 불가하기 때문! (에러문구 보기)

  • 주의사항! 초기화를 안하면 없는 채로 고정이 되기 때문에 오류남. (c)

  • 별도의 초기화가 되지 않은 상수(blank final 변수)는 선언 과정에서 오류 발생됨(에러문구 보기)

> 예외 사항. 생성자를 통해 초기화하는 코드가 포함될 경우!

⇒ 생성자를 통해 c를 초기화 시키니까 오류 없어짐.

  • 생성자에서 단 한 번의 초기화는 가능하다 (한번만 가능)

 

>> 대표적인 변경 불가 상수 : Math 클래스의 PI

  • 여기 잘 보면 S(static)와 F(final) 다 붙어 있음.
  • 값 변경 불가!

 

2. 메서드에 final 키워드가 사용될 경우

> 이제 메서드()에 final 을 붙여보자.

⇒ 메서드()에 final 붙인다는 건 오버라이딩을 못한다는거!

> final 없이 기본

> 메인에서 호출

FinalMethod fm = new FinalMethod();
fm.finalMethod();

SubFinalMethod sfm = new SubFinalMethod();
sfm.finalMethod();
 

 

> 여기서 final 을 붙여보자.

  • final 붙이니까 밑에서 오버라이딩 수행 못함. (빨간 줄 그이는 거 확인)

  • 일반 메서드는 오버라이딩이 가능하다.

 

3. 클래스에 final 키워드가 사용될 경우

> 이제 남은 건 class 에 final 을 붙이는 것.

  • final을 붙였는데도 인스턴스 생성도 잘 되고 출력도 잘 됨!
  • 여기 까지는 문제가 없다!!!
  • 그럼 뭐가 안될까? → extends 를 못함(상속 불가!)

  • final class 는 상속 받을 수 없다! (오류문구 보기)



728x90