ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JAVA]객체 지향 디자인 패턴 - Factory Pattern(팩토리 패턴)
    프로그래밍/Java 2022. 3. 28. 17:55
    반응형

    Factory Pattern이란?

    • 슈퍼 클래스(추상클래스)를 하나를 두고 서브클래스를 여러개 두어 호출 형식에 따라 하나의 자식 클래스의 인스턴스를 리턴해주는 패턴이다.
    • 슈퍼 클래스 호출 부가 많아 질 것 같은 경우 코드가 더 복잡하고 고도화 되는 경우 인스턴스 생성부를 factory 메소드에 갖춰 두어 확장성을 가지게 만들기 위한 패턴이다.
    • 클래스 호출부 형식이 바뀌거나 소스를 직접 수정 및 알 필요 없이 가져다 사용만 하고 싶을 대 사용한다.

     

    Factory Pattern Structure(팩토리 패턴 구조)

    • 인자를 받는 Factory 클래스 및 메소드를 하나 가진다.
    • 부모로 추상클래스 가 하나이상 존재해야한다.
    • 부모클래스로 지정된 것에서 서브 클래스들이 존재해야한다.
    • 자식 클래스는 부모클래스의 메소드를 오버라딩하여 구현 되어있어야 한다.
    • Factory에서는 이 자식 클래스 들 중 하나를 골라 인스턴스를 생성하여 반환해준다.

     

    Factory Pattern Example

    출처. 얄팍한 코딩사전

     

    Component Factory 클래스 

    public class ComponentFactory {
    	public Component getComp (Usage usage) {
    		if(usage == Usage.PRESS) {
    			return new Button();
    		}else if (usage == Usage.TOGGLE) {
    			return new Switch();
    		}else {
    			return new Dropdown();
    		}
    	}
    }

    부모 추상 클래스 

    public abstract class Component {
    	protected abstract String getCompname();
    	public Component() {
    		System.out.println(this.getCompname() + " 생성");
    	}
    }

    자식 클래스들 

    public class Button extends Component{
    	@Override
    	protected String getCompname() {return "버튼";}
    }
    
    public class Switch extends Component{
    	@Override
    	protected String getCompname() {return "스위치";}
    }
    
    public class Dropdown extends Component{
    	@Override
    	protected String getCompname() {return "드랍다운";}
    }

    enum 클래스 몰라도 됩니다.

    public enum Usage {
    	PRESS, TOGGLE, EXPAND
    }

    main에서 호출 하기 

    //main에서 호출하기
    comp1 = ComponentFactory.getComp(Usage.PRESS);
    comp2 = ComponentFactory.getComp(Usage.TOGGLE);
    comp3 = ComponentFactory.getComp(Usage.EXPAND);

     

    Factory Pattern 사용 이유는?

    • Factory 클래스 하나에서 인스턴스를 만들어 반환해 주기 때문에 확장성을 가진다.
    • Component클래스에서 파라미터 값을 변경하게 되었을 때 변경이 용이해진다.

     

    위에 코드만 이렇게만 보개 되면 그냥 별로 효용성 없는 코드로 보이게 될 것 같다. 여기서 소스를 변경해 보도록 하자. Factory클래스 하나에서 인스턴스를 만들어 반환해 주기 때문에 확장성을 가진다고 하였는데, 예를 들어 보자 

    comp1 = new Button();
    comp2 = new Switch();
    comp3 = new Dropdown();

    호출부에서 이렇게 호출을 한다고 하고 이런 컴포넌트를 사용하는 소스가 1000개 이상이라고 해보자. 이 부분을 모두 if문으로 하나의 인자만 받는다고 가정하면 1000개의 컴포넌트 생성하는 곳에서 모두 if문을 작성해 주어야 한다.

    Panel과 TextBox를 추가 했다고 해보자. 그럼 1000개의 소스에 아래와 같이 추가해준다고 하면 확장성이 없어 소스 관리하기 힘들어 진다. 

    public class ComponentFactory {
    	public Component getComp (Usage usage) {
    		if(usage == Usage.PRESS) {
    			return new Button();
    		}else if (usage == Usage.TOGGLE) {
    			return new Switch();
    		}else if (usage == Usage.PANEL) {
    			return new Switch();
    		}else if (usage == Usage.TEXTBOX) {
    			return new Switch();
    		}else {
    			return new Dropdown();
    		}
    	}
    }

    이렇게 하나의 메소드에서 관리하게 되면 if문을 하나만 추가하면 되어 확장성이 넓어진다.

     

    두번째로 이미 생성되어있던 Button클래스에 인자를 받지 않았지만, 인자를 받는다고 가정해 보자. 

    이렇게 되면 모든 Button컴포넌트에 인자를 작성해 주어야 하지만, Factory에서는 한줄만 수정하면 되어서 문제가 없어지게 된다.

    public class ComponentFactory {
    	public Component getComp (Usage usage) {
    		if(usage == Usage.PRESS) {
    			return new Button(true, true);  <- 바뀐 부분
    		}else if (usage == Usage.TOGGLE) {
    			return new Switch();
    		}else if (usage == Usage.PANEL) {
    			return new Switch();
    		}else if (usage == Usage.TEXTBOX) {
    			return new Switch();
    		}else {
    			return new Dropdown();
    		}
    	}
    }
    반응형

    댓글

Designed by Tistory.