시스템 상에서 단 하나의 객체를 생성하고 공유해서 사용하는 설계 패턴
=> 특정 클래스의 인스턴스를 하나만 생성해서 사용해 서버의 자원을 효율적으로 사용
싱글톤은 단 하나의 객체만 생성하고 추가적인 생성을 막아 기존에 생성되어있던 하나의 객체만 계속해서 사용하는것이다.
싱글톤에서 중요한건 프로그램의 동작 순서와 private, static이다.
일단, 다른 객체의 생성을 막아야한다.
생성자를 직접 만들어주되 접근 제어자를 private으로 해 다른곳에서의 추가적인 객체 생성을 막는다.
private Company(){}
그럼 이제 instance인데 private을 통해서 다른곳에서의 생성은 막았지만, 같은 클래스의 내부에서는 private의 접근이 가능하다.
이 때 적용되는게 프로그램 순서인데
프로그램이 동작 시 프로그램 실행 -> 클래스 로드가 비교적 먼저 실행되고, 이후에 다른 클래스에서의 호출 및 초기화가 실행된다.
이 때 일반적인 변수들은 클래스에서의 호출 및 초기화 과정에서 생성이 되는데 static이 붙은 것들은 클래스가 로드 되는 과정에서 먼저 생성이된다.
그래서 프로그램을 시작하면 우선적으로 static이 붙은것들이 meta space 영역에 생성이된다.
private static Company instance=new Company();
static 키워드는 클래스 호출이나 초기화 혹은 클래스 생성과 같은 과정 이전에 클래스 로딩과정에서 생성이된다.
이 때 private 접근제어자로 다른 클래스에서 생성은 막고 instance 변수는 같은 클래스 내에 있기때문에 생성자를 통한 새로운 객체 생성이 가능하다.
그래서 클래스 로드 과정에서, static 영역이 생성되는 과정에 instance라는 변수에 new Company를 하나 생성해 저장해두는것이다.
이렇게되면 instance에는 하나의 new Company가 저장되어있고 다른 클래스에서는 Company의 생성자를 통한 새로운 객체 생성이 불가하니 객체를 단 한 번 생성하고 다른 곳에서는 생성을 못하도록 하는 목적을 달성한것이다.
그런데 instance는 private이기에 instance도 어차피 다른 클래스에서 사용이 불가하다. 그래서 등장한게 getInstance() 메소드이다.
public static Company getInstance(){// 외부에서 접근해 사용하도록 공유
return instance;
}
이 코드는 사실 getter와 같은 일을 한다.
member class 생성시 private String name;을 지정해 getter를 만들어주는것과 같이 이 getInstance도 private 접근제어자라 다른 클래스에서는 못쓰는 instance를 쓸 수 있게 하는것이다.
그래서 이 메소드의 접근제어자는 public으로 설정한다.
MemberDAO dao = new MemberDAO();
에 싱글톤을 적용시키면
MemberDAO dao = getInstance();
이는 프로그램 시작시 클래스 로드과정에서 이미 생성되어있는 값을 가져오는것이라 new 키워드 없이도 사용이 가능하다.
ex)
public class Company{
// 자신의 객체를 생성해 static 변수에 할당 , class loading 시 한번 실행
private static Company instance=new Company();
private Company(){} // 외부에서 객체 생성 불가하게 private 명시
public static Company getInstance(){// 외부에서 접근해 사용하도록 공유
return instance;
}
}
Singleton Design Pattern 적용해서 시스템 상에서 MemberDAO 객체를 단 한 번 생성해서 사용하도록 한다.
public class MemberDAO {
private static MemberDAO instance=new MemberDAO();
private MemberDAO() {}
public static MemberDAO getInstance() {
return instance;
}
getInstance() 메소드는 싱글톤의 대표적인 예이다.
싱글톤이 단 하나의 객체만 생성하고 추가적으로 생성을 막은뒤 기존에 생성되어있던 하나의 객체만 계속해서 사용하는것이므로,
기존 servlet상에서도 코드 수정이 가능하다.
수정전
MemberDAO dao=new MemberDAO();
수정후
MemberVO memberVO=MemberDAO.getInstance().findMemberById(id);
수정전
MemberDAO dao=new MemberDAO();
수정후
MemberDAO dao=MemberDAO.getInstance();