국비필기노트/Java

자바(java)_디자인 패턴, 싱글톤(singleton)

개발..너... 2022. 3. 26. 00:43

▶디자인 패턴

 

예를 들어보자 

우리가 방청소를 할 때 우리는 청소를 하기전에 청소를 빨리 효율적으로 하기 위해 어떤걸 먼저 할 것인지 생각을 할 것이다. 

책상의 먼지를 털고 주변 물건 정리를 한 후에 청소기를 돌리고 걸레질을 하자!라고

 

디자인 패턴도 동일한 개념이다. 

개발을 할 때도 우리는 마주하는 어떤문제에 대하여 어떻게 풀어갈지를 순서대로 생각을 하고 어떻게 해야 더 효율적이게 개발을 할 수 있는지 고민한다.

 

디자인패턴은 설계자들이 "올바른 설계"를 "빨리" 만들 수 있도록 도와주며 기존 환경 내에서 반복적으로 일어나는 문제들을 어떻게 풀어나갈 것인가에 대한 일종의 솔루션 같은 것이다.

 

 

▶SingleTon 패턴

 

예를들어 A라는 계산기코드에는 더하기, 빼기, 곱하기, 나누기같은 오직 기능들만 나열이 되어있는 상태에다. 

이때 우리는 지금까지 더하기를 사용원하면 a1.더하기, a2.빼기 처럼 각각의 객체를 만들어 개별의 메서드를 호출하여 사용을 했다. 

 

그런데 그냥 a1.더하기, a1.빼기, a1.곱하기, a1.나누기처럼 객체를 하나만 만들어서 A에 들어있는 모든 기능을 사용한다고 하면 정말 편하지않을까?

또한 현재 내가 작업하고있는 클래스 페이지를 제외하고도 다른 페이지에도 사칙연산을 할 때 언제든지 가져다쓸 수 있게 a1고정메모리 영역에 올려버리고 전역적으로 사용을 한다면 정말정말 편하지않을까?

 

이 모든게 가능한 것이 SingleTon패턴이다. 

프로그램 내의 여러 곳에서 반복적으로 사용되어야 하는 객체에 대해 전역적인 범위를 갖도록 객체를 생성하고, 이 객체를 여러 곳에서 공유하기 한 클래스 작성 패턴이며 이러한 패턴을 통해 생성된 객체를 싱글톤 객체라고 한다. 

 

 

▶SingleTon 패턴의 장점


프로그램의 전역에서 활용할 재료로 사용되는 공유 기능을 하나만 생성하여 여러 곳에서 재사용함으로 해서 메모리를 효율적으로 사용할 수 있다.


단 한번만 객체를 생성하면 다시 객체를 생성할 필요가 없기 때문에 해당 기능을 사용할 때마다 객체를 일일이 생성해야 하는 번거로움을 피할수 있다.

 

 

▶공통 기능을 포함할 클래스안에서 스스로의 객체를 static으로 선언

 

Calc라고 하는 클래스를 설계를 했다. 

그리고 외부에서 객체를 만드는게 아니라 클래스 안에서 스스로 객체를 선언할 것이다. 

public class Calc{
         static Calc current;   //스스로 객체를 static으로 선언
    }

 

static이 적용된 자원은 메모리의 고정영역에 생성되기 때문에, 클래스 자체의 객체나, 그 안에 포함된 멤버변수, 메서드와는 메모리 상에서 구별된다고 볼 수 있다.

 

그러므로 Calc 클래스 안에 static 형태로 Calc클래스의 객체를 정의하더라도 코드상의 논리적인 연관관계를 위해 하나의 파일에서 정의하는 것일 뿐, 실제로는 Calc 클래스 자체에서 독립된 객체가 되는 것이다.


또한, Calc클래스 이외의 여러 곳에서 new 연산자를 사용하여 객체 할당이 가능하다면 SingleTon 이라는 개념 자체가 성립되지 않으므로, 외부에서 이 객체에 직접적인 접근을 못하도록 은닉시킬 필요가 있다.

 

//객체 선언
public class Calc{
         private static Calc current; // private로 잠궈버린 static 객체
}

 

 

▶Static의 중복할당 방지와 삭제

 

current 객체를 private으로 지정하였기 때문에 객체를 메모리에서 간접적으로 할당하고 삭제하기 위한 메서드가 필요하다. 객체를 메모리에서 제어하기 위해서는 null을 사용한다.
  

//객체 선언
public class Calc{
         private static Calc current; 

// 객체 할당 처리
public static Calc getInstance(){
                    if( current == null ){
                     current = new Calc();
                             } return current;
                          }

 

Static의 기본값은 null이다. 

String의 return값은 ""임을 암기했듯이 Static은 항상 null type을 리턴해야한다고 암기하는 것이 좋다. 

 

Calc의 curret가 스스로 객체를 static으로 선언을 했더라도 한번은 무조건 고정 메모리 영역에 올려야한다. 

객체 할당 부분은 말 그대로 메모리 영역에 값을 올리며 객체를 할당하는 부분이라고 할 수 있는데 if문을 통해 할당되는 값에 조건을 주었다. 

 

만약, current라고 하는 객체의 기본값 null 이라면 즉, 아무런 값이 할당되어있지 않고 선언만 되어있는 상태라면 current라고 하는 객체에 new Calc()라고 객체를 할당해준다. 근데 null이 아닌 다른 어떠한 값이  current에 저장되어있다고 하면 생성되어있는 current에 현재 저장되어있는 값을 return해주겠다는 코드이다. 

 

즉, 이 위의 코드의 의미는 객체가 할당되지 않은 경우에만 할동하도록 하여 중복 할당을 방지하는 기능이다. 


// 메모리에서 삭제
public static void freeInstance(){
                  current = null;
                        }
                       }

 

current안의 객체를 삭제를 원한다면 객체에 null을 대입하여 메모리에서 삭제한다.

 

 

▶new 연산자를 사용한 객체 할당 금지하기

 

우리가 아무리 current의 메모리를 할당하고 삭제하고 private로 잠궈둔다고 해도 Calc에는 기본생성자가 있다. 누군가가 기본생성자를 통해 Calc의 데이터를 바꿀 수도 있고 값을 초기화 시킬 수 있는 것이다.

 

그래서 우리는 기본 생성자도 private 형태로 정의하여 객체 생성자를 은닉처리할 필요가 있다.
즉, new 연산자를 사용한 객체 할당이 금지된다.

private Calc(){
super();
           }
      }

 

위의 코드가 Calc()코드를 private로 잠궈버린 코드이다.

이 코드까지 넣어야지만 완벽한 싱글톤코드가 만들어진 것 이다. 

 

 

▶싱글톤 예제

 

[Calc클래스]

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package Static;
 
 
public class Calc { 
    // ---------- 싱글톤 객체 생성을 위한 준비 시작 ---------------
    private static Calc current;
    
    public static Calc getInstance() {
        if( current == null ) {
            current = new Calc();
        }
        
        return current;
    }
    
    public static void freeInstance() {
        current = null;
    }
    
    private Calc() {
        super();
    }
    // ---------- 싱글톤 객체 생성을 위한 준비 끝 ---------------    
    
    // 이 클래스가 구현해야 하는 기능
    public void plus( int x, int y ) {
        int z = x + y;
        System.out.println( x + " + " + y + " = " + z );
    }
    
    public void minus( int x, int y ) {
        int z = x - y;
        System.out.println( x + " - " + y + " = " + z );
    }
    

    
cs

 

 

[Main클래스]

 



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
package Static;
 
public class Main02 {
 
    public static void main(String[] args) {
    
        // 별도의 객체에 참조시키는 경우
        Calc loader1 = Calc.getInstance();
        loader1.plus(1020);
        
        // 참조처리를 생략하고 직접 사용하는 경우
        Calc.getInstance().minus(10050);
        
        Calc loder2 = Calc.getInstance();
        
    }
 
}
    
cs

싱글톤을 사용하는 방법이다.