변수 유형에 따른 용도
| 변수 유형 | 선언 위치 | 사용 범위 | 메모리 | 생성과 소멸 |
|---|---|---|---|---|
| 지역변수 | 함수 내부에 선언 | 함수 내부에서만 사용 | 스택 | 함수가 호출될 때 생성, 함수 끝나면 소멸 |
| 멤버변수 | 클래스 멤버변수로 선언 | 클래수 내부에서 사용 | 힙 | 힙에 생성, 가비지 컬렉터가 메모리를 수거 시 |
| static변수 | static 예약어 사용 | 클래스 내부에서 사용,private아니면 클래스 이름으로 다른 클래스에서 사용 가능 | 데이터 영역(스태틱 영역) | 프로그램이 처음 시작할때 상수와 함께 생성, 프로그램 끝나고 메모리 해제될때 소멸 |
부연설명
싱글톤 패터을 사용하는 이유는 정보를 보관하고 공유하고자 하는 클래스(회사 클래스)가 한번의 메모리만 할당하고 그 할당한 메모리에 대해 객체(인스턴스)로 관리하기 위함이다. 이렇게되면 여러 클래스에서 각자 "회사"클래스의 생성자를 호출하더라도 처음 한 번 생성된 객체(인스턴스)를 반환해주기 떄문에 정보 공유 차원에서의 변수 관리 즉, 동기화에 유리하다.
`싱글톤 패턴으로 클래스 구현하기`
1. 생성자(constructor)를 private로 만들기
- 생성자가 하나도 없는 클래스는 컴파일러가 자동으로 디폴트 생성자를 만들어준다. 그런데 컴파일러가 만들어 주는 디폴트 생성자는 항상 public이다. 생성자가 public이면 외부 클래스에서 인스턴스를 여러 개 생성할 수 있다. 따라서 `싱글톤 패턴에서는 생성자를 반드시 명시적으로 만들고 그 접근 제어자를 private로 지정`
2. 클래스 내부에 static으로 유일한 인스턴스 생성하기
- 단계1에서 외부 인스턴스를 생성할 수 없도록 만들었다. 하지만 우리가 프로그램에서 사용할 인스턴스가 하나 필요하기 때문에 클래스 내부에 하나의 인스턴스를 생성
3. 외부에서 참조할 수 있는 public 메서드 만들기
- private로 선언한 유일한 인스턴스를 외부에서도 사용할 수 있도록 설정, 이를 위해 public 메서드로 생성하고, 인스턴스를 반환한다. 이때, 인스턴스를 반환하는 메서드는 반드시
static으로 선언한다.
public calss Company{
public static Company getInstance(){
if(instance == null){
instance = new Company();
}
return instance; //유일하게 생성한 인스턴스 반환
}
}
인스턴스를 외부에서 참조할 수 있도록 public getInstance() 메서드를 구현
추가 연습(23.01.15)
public class Singleton {
private static Singleton InstanceEx;
private String companyName;
private String companyAddr;
private Singleton() { // 디폴트 생성
}
public static Singleton getInstance() {
if(InstanceEx == null) {
synchronized (Singleton.class) {
InstanceEx = new Singleton();
}
}
return InstanceEx;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getCompanyAddr() {
return companyAddr;
}
public void setCompanyAddr(String companyAddr) {
this.companyAddr = companyAddr;
}
}
실행문
public class SingletonEx2 {
public static void main(String[] args) {
Singleton companyInfo = Singleton.getInstance();
companyInfo.setCompanyAddr("회사 주소 [Setter]로 접근");
companyInfo.setCompanyName("회사 이름 [Setter]로 접근");
System.out.println("companyName: " + companyInfo.getCompanyName() );
System.out.println("companyAddr: "+ companyInfo.getCompanyName());
}
}
결과 :
companyName: 회사 이름 [Setter]로 접근
companyAddr: 회사 이름 [Setter]로 접근