오늘 포스팅 할 내용은 정적 팩토리 메서드에 관한 내용이다.


내용 의 상당수는 (Effective Javaa 2/E - 2판)의 도움을 받았고,


개인적인 의견을 덧 붙여 해당 내용을 풀어 설명할 것 이다.


인스턴스를 생성하기 위해서는 Class 원칙에 따라, 생성자를 호출해야 한다.


Person p = new Person( );


Class의 이름은 캡슐화를 위해 Class의 내용을 아우를 수 있는 이름을 짓기 마련이다.


따라서, 생성자의 이름만을 봐서는 감이 안올때가 있다.


또한, 여러가지 매개변수를 받는 생성자를 만들 때도, 생성자의 매개변수를


설명할 방법이 딱히 없다. 하지만, 정적 팩토리 메서드의 활용 여부에 따라 


코드의 가독성을 높일 수 있다. (여기서 정적은 static을 가리킨다.)


그로인해 아래와 같은 장점들이 존재한다.


정적 팩토리 메서드는 해당 클래스 인스턴스에 이름을 지어줄 수 있다.


public class Person{

  private String name;

  private Person( ){

  }

  

  public static Person newInstance(){

    return new Person( );

  }

  public static Person newInstance(String name){

    this.name = name;

    return new Person( );

  }


  public static void main(String[] args){

    Person p  = Person.newInstance(); // 평범한 인스턴스 생성

    Person p2 = Person.newInstanceByName("Mommoo"); // name속성을 가지는 인스턴스 생성 

  }

}


인스턴스의 갯수를 제어 할 수 있다. 이를 응용한 것이 싱글톤 패턴 이다.


public class Person{

  private final Person p = new Person( );


  private Person( ){

  }


  public static Person getInstance(){

    return p;

  }


  public static void main(String[] args){

    Person p = Person.getInstance( ); // 이미 존재하고 있는 객체 리턴

  }

}


생성자엔 반환값이 없지만, 필요시에 적절한 반환값을 만들어 줄 수 있다.


public class Person{

  private Person( ){ 

  }


  public static class Doctor{

    private Doctor(){

    }

  }


  public static Doctor getDoctor( ){

    return new Doctor( );

  }


  public static void main(String[] args){

    Doctor doctor = Person.getDoctor( );

  }

}


위의 예시는 반환값을 특정 Class로 했지만, 설계에 따라 어떠한 반환값이든 가능하다.


생성자를 감싸는 구조이므로, 유지보수와 성능 개선에 좋다.


위의 예시중 getDoctor 메서드가 new Doctor( )란 새로운 인스턴스를 리턴하지만,


개발자가 싱글톤으로 리턴하는 코드로 변경한다고 가정해보자.


public class Client{


  public static void main(String[] args){

    /** 클라이언트는 변경사항이 없다. 

      *  getDoctor( ) 메서드가 내부적으로 어떻게 변경되는지, 어떻게 쓰이는지 알 필요조차 없다.

      *  클라이언트는 단순히 Doctor라는 객체를 쓰는데만 집중한다. 

      */

    Doctor doctor = Person.getDoctor( );  

  }

}


public class Person{

  private Person( ){ 

  }


  public static class Doctor{

    

    private final Doctor d = new Doctor( );


    private Doctor(){

    }

  }


  public static Doctor getDoctor( ){

    return Doctor.d;   //new Doctor( ) 에서 Doctor.d 로 변경되었다.

  }


  public static void main(String[] args){

    Doctor doctor = Person.getDoctor( );

  }

}


이러한 장점들이 있는 반면, 단점들은 무엇이 있을까? 


먼저, 정적 팩토리 메서드의 사용을 권하기 위해서 private 제어자를 사용해 생성자를 막는다.


그로인해, 해당 클래스를 상속 할 수 없다. 왜냐하면 상속받을 생성자가 없기 때문이다.


또한, 다른 정적 팩토리 메서드는 다른 메서드와 크게 구분이 가지 않는다. 


만약 생성자를 이용한다고 가정해보자.


클래스를 설계 할때는 클래스 이름과 동일하고 반환값 자리가 아예 존재 하지 않는


메서드라는 특정 표식이 있고, 클래스를 쓸때도, new 생성자( ); 처럼


new 연산자를 통해 생성하므로, 생성자의 느낌을 물씬 주지만


정적 팩토리 메서드는 다른 정적 메서들과 차이점이 존재하지 않는다.


Class를 설계한 개발자 조차도 주석을 달아 놓지 않으면, 후에 다시 자신이 설계한 클래스를


봤을 때, 잊어먹 을 수 있다. 


결국 정적 팩토리 메서드를 활용한 클래스를 사용할때는, API나 사용법을 들어야한다.


(물론 생성자를 사용할 때도 어느정도 API나 사용법등을 참고해야할 때가 있다.)




'Java [Effective Java 2_E]' 카테고리의 다른 글

JAVA - 열거자료형 Enum 사용하기(1)  (0) 2016.11.11
Java - Builder 패턴 적용하기.  (3) 2016.10.08

포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee

오늘 포스팅 할 내용은 Static에 대해 알아 볼 것이다.


프로그래밍 용어로써의 Static은 정적의,고정의 뜻으로 생각하면 된다.


자바에서는 어떻게 쓰이나 아래의 설명을 보자.


먼저, 자바는 Statically Type Variable (정적 타입 변수)를 가진다.


예를 들어, 변수를 사용할때 아래와 같이 사용한다.


int a = 1;


int라는 자료형을 미리 정해줌으로써 a 변수는 정수 실제 데이터 밖에 싣지 못한다.


미리 자료형을 고정하므로 Static개념이다.


많은 스크립트 언어가 윗 개념과의 반대인 Dynamically Type Variable(동적 타입 변수)를 가진다.


예를 들어, 자바스크립트에서는 아래와 같이 변수를 사용한다.


var a = 1;


여기서는 var(Variable의 약자) 이라는 변수 표시와 함께 변수명 a를 선언 했을때, 실제데이터의 종류에 따라 동적으로


타입이 결정된다. 윗 예시는 실제데이터가 정수형 이므로 a의 자료형은 정수형이 되는것이다. 



두번째로, 자바는 static 예약어를 제공한다. 윗 개념에서 살펴 보았드시, Static은 정적의 고정의 뜻으로 생각하면 된다. 아래의 예시를 보자.


public class StaticTest{


 static public int a = 1;


 public int b = 3;


 static public void add(){

 }

}


윗 예시는 int 형 변수 a 를 static 예악어를 통해 고정시켜 놓았다. 어딜 고정 시켜 놓은 것 일까?


답은 메모리에 미리 고정시켜 놓은것이다.


클래스 안의 변수를 사용하기 위해서는 인스턴스를 생성해야 한다. 

ex)

 StaticTest st = new StaticTest(); 

 st.a;

 st.add; 

<인스턴스 변수. 변수 or 메서드>


하지만, static 예약어를 사용하면 인스턴스를 생성하기 전에 미리 메모리에 올려놔 고정시킨다.


이렇게 되면 무슨 특징이 있을까? 아래와 같은 특징이 있다.




1. 인스턴스를 생성한 후 이용가능 하던 변수가 static 예약어를 사용함으로써, 미리 메모리에 올라가 있으므로, 인스턴스 생성 없이 바로 사용가능하다.


  StaticTest.a; 

  StaticTest.add();  

<클래스.변수 or 메서드>


2. StaticTest 의 인스턴스를 몇개를 생성하든 a의 변수는 이미 메모리에 올라가 있으므로,

  

  인스턴스 마다 변수 a가 생기는 것이 아니라 메모리에 미리 올라가 있던 변수 a를 공유한다. 


  따라서 static 예약어를 사용한 변수는 공유변수 라고도 불린다.


  변수a를 공유하므로 변수a크기 만큼 메모리를 아낄 수 도 있다. 


  메서드도 똑같이 생각하면 된다.


3. 만약 변수b를 static 메서드 add안에다가 사용하면 오류가 발생한다. 

  

  이유는 int b는 StaticTest의 인스턴스가 생성되어야 쓸수 있는 멤버변수지만,

  

  static public void add()는 인스턴스가 생기길 기다려주지 않고 바로 메모리에 올라가기 때문에 


  StaticTest안에 일반 멤버변수 b는 쓰지 못한다.



여기까지가 준비한 포스팅 내용이다. 프로그래밍 개념으로서의 static은 고정하다, 정적이다. 라는 뜻이므로


자바 뿐만 아니라 static 개념이 나오는 모든 프로그래밍을 윗 개념으로 이해하면 좋을 것 이다.





'Java' 카테고리의 다른 글

JAVA BufferedReader readLine에 관하여.  (2) 2016.04.09
Java foreach문(향상된 for문)  (0) 2016.03.30
자바 enum 열거형  (0) 2016.01.27
JAVA - 익명클래스(Anonymous class)란?  (3) 2016.01.20
JAVA의 삼항연산자  (4) 2015.12.11

포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee

+ Recent posts