학교 공부

[디자인패턴] factory method 패턴

연듀 2021. 11. 18. 14:20
public class Home {
    public Apple getAppleForBreakFast(String kind){
        Apple apple = null;
        if(kind.equals("busa")) apple = new Busa();
        if(kind.equals("hongok")) apple = new Hongok();
        apple.wash();
        return apple;
    }
}

// new 구체적인 클래스이름();
// hongok을 쓰고 싶으면 new Hongok(); 해줘야 한다.(변경 되어야 함)
// -> 필요로 하는 인스턴스를 직접 만들어 사용하기 때문에

// 객체를 생성하는 부분이 계속 변경되어야 함.

public abstract class Apple {
    public abstract void wash();
    public abstract void peel();
    public abstract void slice();
}


public class Restaurant {
    public Apple servingApple(String kind){
        Apple apple = null;
        if(kind.equals("busa")) apple = new Busa();
        if(kind.equals("hongok")) apple = new Hongok();
        apple.wash();
        apple.peel();
        apple.slice();
        return apple;
    }
}

public class Hongok extends Apple{
    @Override
    public void wash() {
        System.out.println("Hongok: wash");
    }

    @Override
    public void peel() {
        System.out.println("Hongok: peel");
    }

    @Override
    public void slice() {
        System.out.println("Hongok: slice");
    }
}

public class Busa extends Apple{
    @Override
    public void wash() {
        System.out.println("Busa: wash");
    }

    @Override
    public void peel() {
        System.out.println("Busa: peel");
    }

    @Override
    public void slice() {
        System.out.println("Busa: slice");
    }
}

 

 

사과의 종류를 추가 하는 경우 사과를 필요로 하는 모든 곳에서 새로운 사과를 추가하도록 코드 변경해야 한다. 

 

public class Hongro extends Apple{
    @Override
    public void wash() {
        System.out.println("Hongro: wash");
    }

    @Override
    public void peel() {
        System.out.println("Hongro: peel");
    }

    @Override
    public void slice() {
        System.out.println("Hongro: slice");
    }
}


public class Home {
    public Apple getAppleForBreakFast(String kind){
        Apple apple = null;
        if(kind.equals("busa")) apple = new Busa();
        if(kind.equals("hongok")) apple = new Hongok();
        if(kind.equals("hongro")) apple = new Hongro();
        apple.wash();
        return apple;
    }
}

public class Restaurant {
    public Apple servingApple(String kind){
        Apple apple = null;
        if(kind.equals("busa")) apple = new Busa();
        if(kind.equals("hongok")) apple = new Hongok();
        if(kind.equals("hongro")) apple = new Hongro();
        apple.wash();
        apple.peel();
        apple.slice();
        return apple;
    }
}

 

restaurant, home 모두 다 코드를 변경해야 한다. 

 

=> 변경되는 부분을 클래스 캡슐화 한다. 

 

 

 new 연산자를 객체 생성하기 위해 직접 사용하지 않는다. 

객체를 생성하는 메서드를 factory 메서드라고 한다. 

 

새로운 사과를 factory 메서드에서 생성하고,

restaurant, home에는 전혀 영향을 받지 않는다. 

 

 

 

public class AppleFactory {
    public static Apple getApple(String kind){
        Apple apple = null;
        // 새로운 사과 추가
        if(kind.equals("busa")) apple = new Busa();
        if(kind.equals("hongok")) apple = new Hongok();
        if(kind.equals("hongro")) apple = new Hongro();
        return apple;
    }
}

//getApple 메서드는 appleFactory의 인스턴스 메서드일 필요가 없다.
// static이면 된다.

public class Restaurant {
    public Apple servingApple(String kind){
        Apple apple = AppleFactory.getApple(kind);
        // AppleFactory를 참조해 원하는 apple을 가져온다.
        apple.wash();
        apple.peel();
        apple.slice();
        return apple;
    }
}

public class Home {
    public Apple getAppleForBreakFast(String kind){
        Apple apple = AppleFactory.getApple(kind);
        apple.wash();
        return apple;
    }
}

 

 

객체를 하나만 생성하는 싱글톤 패턴을 사용 할 수도 있다. 

AppleFactory에서 객체 하나를 생성하고

home, restaurant에서 동일한 인스턴스를 참조한다. 

이 인스턴스는 Apple 인스턴스를 생성하는 작업만 한다.

 

싱글톤을 사용한 방법

public class AppleFactory {
    private static AppleFactory instance = null;
    private AppleFactory() {};
    public static AppleFactory getInstance(){
        if(instance == null) instance = new AppleFactory();
        return instance;
    }
    public Apple getApple(String kind){
        Apple apple = null;
        // 새로운 사과 추가
        if(kind.equals("busa")) apple = new Busa();
        if(kind.equals("hongok")) apple = new Hongok();
        if(kind.equals("hongro")) apple = new Hongro();
        return apple;
    }
}

public class Home {
    public Apple getAppleForBreakFast(String kind){
        AppleFactory factory = AppleFactory.getInstance();
        Apple apple = factory.getApple(kind);
        apple.wash();
        return apple;
    }
}

public class Restaurant {
    public Apple servingApple(String kind){
        AppleFactory factory = AppleFactory.getInstance();
        Apple apple = factory.getApple(kind);
        apple.wash();
        apple.peel();
        apple.slice();
        return apple;
    }
}

 

 

Main

 

 

 

 

=>factory method는 객체를 생성하는 로직을 따로 분리하는 메서드이다.