안녕하세요. 풀스택개발자를 지향하는 진쓰입니다.

디자인패턴 팩토리메소드 포스팅 시작하겠습니다.




목적

- 개발자는 객체를 생성해서 사용해야하는데, 어떤 객체를 생성할지, 어떤 객체가 생성가능할지 없을 때 사용할 수 있습니다.




활용

- 생성할 객체 타입을 예측할 수 없을 때 활용합니다.


- 객체 생성의 책임을 하위 클래스에게 위임시키고, 어느 하위 클래스에게 위임했는지에 대한 정보를 은닉하고자 할 때 활용합니다.




목적과 활용으로 봐서는 감이 안오실수있습니다. 예제를 통해 살펴보고 설명하도록 하겠습니다.

예제

- 교통수단이 되는 것을 만들어내는 회사가 있다. 이회사는 택시와 자전거를 만들어내는 회사다.





코드리뷰


 - 구성




 TransProduct.java

 public abstract class TransProduct {

    abstract void useTrans();
}




 TransProduct_Taxi.java

 public class TransProduct_Taxi extends TransProduct {

    @Override
    void useTrans() {
       System.out.println("Using Taxi");    
    }
}



 TransProduct_Bicycle.java

 public class TransProduct_Bicycle extends TransProduct {

    @Override
    void useTrans() {
       System.out.println("Using Bicycle");       
    }
}



.



 TransCreator.java

 //추상 클래스.

//Caller는 Interface혹은 abstract 클래스를 통해, Callee와 연결해야된다.
public abstract class TransCreator {
    //TransProduct 생성하는 팩토리 메소드(자전거, 택시)
    public abstract TransProduct transCreate(String trans);
}




 RealTransCreator_TransCompany.java

 public class RealTransCreator_TransCompany extends TransCreator {

    @Override
    public TransProduct transCreate(String trans) {
       
       if(trans.equals("taxi")){
           return new TransProduct_Taxi();
       }
       else{
           return new TransProduct_Bicycle();
       }   
       
       
    }
}



Main.java 

 public class Main {

    public static void main(String[] args) {
       
       //교통수단을 만들어내는 생산자 선언.
       TransCreator tc = new RealTransCreator_TransCompany();
       
       //Caller(Main)은 Callee를 직접변수를 선언하지않고 생성.
       //항상 인터페이스(중간매체, 추상클래스포함)를 통해 생성.
       
       TransProduct tp;
       
       //교통수단 - 자전거 생성
       tp = tc.transCreate("bicycle");
       
       //자전거 기능 이용.
       tp.useTrans();
       
       //교통수단 - 택시 생성
       tp = tc.transCreate("taxi");
       
       //택시 기능 이용.
       tp.useTrans();
    }
}



결과화면





UML




- UML 설명

TransCreator 클래스가 부모 클래스 입니다.

RealTransCreator가 진짜 객체를 만드는 클래스 입니다

여기선 RealTransCreator가 Bicycle과 Taxi를 생성하여(TransProduct)반환한다.



*) 여기서 회사가 만들어내는 제품이 늘어난다면?

(1) TransProduct 상속받는 클래스 추가합니다.

(2) RealTransCreator_TransCompany(Product를 생성하는 클래스)에서도 transCreate 수정합니다.

(Product가 늘어났으니!,dependency 관계니깐)



 RealTransCreator_TransCompany는 TransProduct_Bicycle, TransProduct_Taxi와 dependency 관계라서 Product가 늘어났다는것은 RealTransCreator_TransCompany역시 수정되어야 한다는 의미이다.



점선화살표는 dependency 를 의미합니다.





객체지향 원칙

Caller는 Callee를 직접 만들어 호출하지 않는다.


=> 여기선, TransCreator에서 TransProdcut_Taxi와 TransProduct_Bicycle을 만들 수 있지만, 

RealTransCreator_TransComapny 라는 sub 클래스를 하나 둬서 , 실제 TransProduct를 생성하여 반환하도록 하였다.


이처럼 객체지향언어에서는 Caller는 Callee를 직접만들어 호출하지않고 한단계를 더 둔다=>결합도를 떨어트리기 위해서이다.







정독해주셔서 감사합니다 :)

안녕하세요 풀스택개발자를 꿈꾸는 진쓰입니다.

디자인패턴 - 싱글톤 패턴 포스팅 시작하겠습니다.

부족한부분은 포스팅 밑부분, 싱글톤 패턴 영상으로 보충하실수있습니다.




의도

=> 클래스를 생성하는 인스턴스가 오직하나여야 한다.


인스턴스 접근 혹은 생성 역시 한가지의 방식으로만 제공하여 오직, 

하나의 인스턴스만 생성하고 이용할수 있게된다.




활용

- 클래스 인스턴스가 오직하나여야함을 필요로 하는곳에 활용할 수 있습니다.

- 모든 클라이언트가 하나의 인스턴스만 사용해야하는 경우에 활용할 수 있습니다.


싱글톤 패턴 만드는 방법!  딱 3가지만 숙지하시면 됩니다.

1. private 생성자 선언 합니다.


2. private static 인스턴스 변수 선언 합니다.


3. public static getInstance() method 구현 해야합니다.






예제 코드로 살펴보시겠습니다.


예제상황: 안드로이드 시스템에서 스피커객체는 유일하게 하나만 존재해야 하며, 

스피커의 객체에서 attribute값 중하나인 시스템사운드 크리를 읽어 오려한다.





시스템 스피커의 클래스 선언부입니다.


 SystemSpeaker.java

 public class SystemSpeaker {

    //원래는 private, getter, setter 필요. 편의상.
    public int systemVol = 5;
    //2. private static 인스턴스 변수
    private static SystemSpeaker ss = new SystemSpeaker();
    
    //3.public static getInstance() method 구현.
    public static SystemSpeaker getInstance(){   
       //if(ss==null){
       //  ss = new SystemSpeaker();
       //}
       return ss;     
    } 
    //1.private 생성자.
    private SystemSpeaker(){    
    }
  
    //4.다양한 방법 존재.
    /*
     * 시작과 동시에 객체를 생성할것인가 혹은, 프로그램 러닝중에 객체를 생성할 것인가.
     *
     *
     */
}


위와 같이 SystemSpeaker.java 를 생성하면, 자바 가상머신이 시작할때 바로 객체가 미리 생성하고 프로그램이 시작된다.


아래와같이 SystemSpeaker.java를 생성하면 프로그램이 실행중에 객체를 1번 생성하게된다. (필요할때 생성하는 방식)


어느것을 선택할지는 개발자 몫이다.


  SystemSpeaker.java

 public class SystemSpeaker {

  
    public int systemVol = 5;  
    //2. private static 인스턴스 변수
    private static SystemSpeaker ss;
    //3.public static getInstance() method 구현.
    public static SystemSpeaker getInstance(){ 
       if(ss==null){
           ss = new SystemSpeaker();
       }
       return ss;     
    }
    
    //1.private 생성자.
    private SystemSpeaker(){
       
    }

}

.


스피커 객체를 생성하고 값을 읽어오는 메인부입니다.

 Main.java

 public class Main {

    public static void main(String[] args) {    

       //객체1생성

       //SystemSpeaker ss = new SystemSpeaker();

       SystemSpeaker ss1 = SystemSpeaker.getInstance();

       //객체2생성

       SystemSpeaker ss2 = SystemSpeaker.getInstance();

       //객체의 주소 비교.

       System.out.println(ss1);

       System.out.println(ss2);   

       //객체의 attribute 읽어오기.

       System.out.println(ss1.systemVol);

       System.out.println(ss2.systemVol);       

    }

}

 



객체의 주소를 비교해본 결과, 같은 객체임을 알수있다.






정리

- 유일하게 존재하는 인스턴스 접근을 통제하고자 할 때 사용하면 됩니다.


- 싱글톤 패턴을 사용하면 인스턴스가 오직한개이기때문에 변수영역을 줄일 수 있습니다.





정독해주셔서 감사합니다. :)



+ Recent posts