Loading...

JAVA / / 2022. 1. 18. 13:54

자바 21강. 싱글톤 패턴, pooling 기법

반응형

패턴 -> 디자인 패턴 -> 설계도를 패턴으로 만들까?

설계도를 만들어 놓으면 누구나 동일하게 만들 수 있다.

 

 

a( ) 메서드에서 사자 클래스를 호출하기 위해 new를 사용하여 heap공간에 띄웠다.

 

이후 a( )가 종료되면 heap에 저장되어 있는 사자 데이터들이 사라지는 것이 아닌,

사자 데이터들을 가리키는 주소 값 s가 사라지게 된다.

 

그러면 heap의 사자는 어떻게될까?

가비지 컬렉션이 되어버린다.

 

a( )에서 만들어놓은 사자 데이터를

b( )와 c( )에서 사용하고 싶은데,

 

대부분의 신입사원들은 필요할 때마다 사자 클래스를 new를 하여,

띄워져 있는 사자를 공유하지 않고

heap공간에 매번 새로운 데이터를 띄울 것이다. 

 

 

 

 

 

카페에서 손님 한 명 올 때마다 커피 머신을 돈 주고 사서 커피 한잔 뽑고 쓰레기통에 버리고,

또 한 명 올 때마다 커피 머신 사서 커피 뽑고 쓰레기통에 버리지는 않는다.

손님이 올 때마다 새로운 커피머신을 사는 행위가

-> 계속 new 해서 새로운 데이터를 힙에 띄우는 행위이다.

 

 

실제 세상에서는 커피 머신을 2개 정도 준비해둔 뒤,

손님들이 올 때마다 그 커피 머신을 공유해서 사용한다.

 

하지만 자바에서는 2개의 static이 공존할 수 없기 때문에

커피 머신을 static 상태로 띄울 수 없다.

그래서 커피 머신은 new로 동적 할당해야 한다.

 

이 new를 한 번 또는 두세 번만 한 뒤 공유해서 사용할 수 있도록 하는 것이 패턴이다.

 

우리는 싱글톤 패턴을 공부할 것이다.

 


 

싱글톤 패턴은 new를 사용해 커피 머신을 한 개만 만들어서 공유하는 것을 말한다.

 

싱글톤 패턴 : 객체를 하나만 유지하는 것

두 개, 세 개도 가능함

 


 

수영장에 손님이 올지 안 올지 모른다.

 

무조건 오는 걸 알고 있다면 튜브를 미리 불어놓을 것이다.(static)

 

그런데 손님이 한 명 왔을 때 직원이 튜브 한 개를 부는 것은 new 하는 것이다.(heap)

 

손님이 들어올 때마다 튜브를 불어놓으면 어떻게 될까?

튜브가 남아 돌게 된다.

 

손님이 다 놀고 나가면 튜브가 남기 때문에 바람을 빼야 한다.

 

이게 필요할 때마다 new 하고, 사용이 끝나면 가비지 컬렉션이 되는 것이다.

 

초보 개발자가 계속 new 하여 코드를 짜는 게 쉽기 때문에 이런 방식을 사용한다.

 

static을 쓰면 미리 튜브를 불어놓을 수 있지만 하나밖에 못 분다.

 

new를 쓰면 원할 때, 원하는 만큼 튜브를 불어놓을 수 있다.

그러면 무조건 new를 사용해 heap에 띄울 것이다.

 

하지만 계속 new를 하면 남는 튜브가 생긴다.

(들어올 때마다 불고, 나갈 때마다 바람 빼고)

 

 

난 무조건 다섯 개만 만들 거야.

보니까 5명 이상 동시에 이용하는 경우가 없더라고.

근데 미리 만들어두진 않을 거야.

손님이 들어올 때마다 불건데 5개까지만 불거고,

손님이 나가면 튜브에 바람 빼지 마.

그리고 손님 들어오면 5개 중에 남는 튜브 줘서 공유하자.

 

Pooling 기법 : 하나 혹은 일정한 개수를 띄워놓고 공유하는 기법

 

수영장은 물을 공유해서 사용한다.

손님이 들어올 때마다 물을 갈지 않으니까!

 

pooling 기법을 쉽게 사용하기 위해 팀장이 패턴을 만들어놓는다.

 

싱글톤 패턴 : 객체를 하나만 만들어서 공유할 수 있는 코드 설계도

package ex11;

// 패턴 -> 디자인 패턴 -> 설계도를 패턴으로 만들까?
// 설계도를 만들어 놓으면 누구나 동일하게 만들 수 있음
// 싱글톤 패턴
class 튜브 {
    // main 실행전에 static으로 미리 띄울수 있음
    private static 튜브 instance = new 튜브();
    // 튜브 2개로 pooling기법 사용
    // private static 튜브 instance2 = new 튜브();

    private 튜브() { // 생성자 접근불가, new 불가능

    }

    public static 튜브 getInstance() {
        System.out.println("만들어진 튜브를 가져옵니다.");
        return instance;
    }
}

public class SingleEx01 {
    public static void main(String[] args) {
        튜브 t1 = 튜브.getInstance();
        튜브 t2 = 튜브.getInstance();

        System.out.println(t1.hashCode());
        System.out.println(t2.hashCode());
    }
}

(12) 생성자에 private를 붙이면 new를 할 수 없게 된다.

heap에 띄울 수 없는 것이다.

 

그러면 어디에서도 튜브 클래스를 메모리에 띄울 수 없게 된다.

 

생성자 앞에 public을 붙여주면 어디에서든 new가 가능하다.

 

(8) 이때 main이 실행되기 전에 static으로 미리 튜브 하나를 메모리에 선언하게 되면

private static 튜브 instance = new 튜브( );

튜브 타입의 변수 instance 딱 하나만 사용할 수 있게 된다.

 

변수를 불러오기 위해 클래스 이름 위에 Alt + Enter 하게 되면

getter, setter 메서드를 만들 수 있게 된다.

 

(16) 지금 우리는 상태의 값을 변경하지 않을 것이므로 getter만 사용하자.

 

튜브 타입의 instance를 리턴해주는 static 메서드를 만들고

(17) 확인하기 위해 출력문도 하나 만들어주었다.

 

(24, 25) heap에 튜브가 만들어졌는지 확인하기 위해

main에서 변수 t1, t2를 선언하여 메서드를 호출해준다.

 

정상적으로 "만들어진 튜브를 가져옵니다."

문장이 출력될 것이다.

 

(27, 28) t1과 t2가 메모리의 같은 주소를 가리키고 있는지 확인하기 위해

두 변수의 주소값(=해시코드)을 출력해준다.

 

해시 코드를 확인하여 t1과 t2가 같은 메모리 공간을 가리키는 것을 확인할 수 있다.

 

즉, 메모리에 튜브는 하나밖에 안 띄워져 있다!

 

Ctrl + 클릭
Object 클래스의 메서드 hashCode( )

hashcode( ) 메서드는 컨트롤 클릭해서 확인해보니 Object클래스에 있다.

 

튜브 타입의 t1은 튜브 클래스인데, 어떻게 Object 클래스의 hashcode( ) 메서드를 사용했을까?

 

튜브 클래스는 hashcode 메서드를 들고 있지 않는다.

 

extends Object(상속)를 하지 않았지만 object는 튜브의 부모 클래스라는 말이다.

 

자바의 모든 클래스는 오브젝트 클래스이다.

모든 클래스에 extends object가 생략되어있는 것이다.

 

* 하지만 최상위 부모 클래스에게만 오브젝트 클래스에게 상속되어 있는 것이다. *

 

 

 

 

[출처]

 

https://cafe.naver.com/metacoding

 

메타코딩 : 네이버 카페

코린이들의 궁금증

cafe.naver.com

 

메타 코딩 유튜브

https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9

 

메타코딩

문의사항 : getinthere@naver.com 인스타그램 : https://www.instagram.com/meta4pm 깃헙 : https://github.com/codingspecialist 유료강좌 : https://www.easyupclass.com

www.youtube.com

 

반응형