CS

[DesignPattern] Factory pattern 알아보기

뱅타 2022. 4. 17. 15:32

프로그래밍을 시작한지 어느덧 1년이 넘었네요. 그렇지만 제대로된 디자인 패턴에 대한 공부를 해본 적이 없다는 생각이 들어 스터디를 시작하게 되었습니다. 그 중 첫주제인 factoryMethod pattern을 공부하려다 보니 factory pattern이 다양한 pattern(Singleton, Builder)의 base가 되더군요. 그래서 factory pattern에 대해 우선적으로 정리를 하려고 합니다.

들어가기에 앞서 추상클래스와 추상메서드에 대해 알고 가면 이해하기 조금 더 편할 듯 합니다.

정리한 코드가 보고싶으신 분은 아래 링크를 확인해 주세요.

GitHub: Factory pattern 패키지

Factory pattern

Client 측에서 factory를 통해 간단하게 원하는 Object(Cat, Dog)를 생성할 수 있습니다. 뒤의 Object(Cat, Dog)와 같은 객체들의 생성 과정을 알지 못해도 되죠.

image-20220417133824314

출처: Design pattern, Factory Pattern, 디자인패턴, 팩토리패턴: 코드없는 프로그래밍

위의 이미지와 같이 고양이(Cat), 개(Dog)를 호출하는 프로그램을 구현한다고 가정했을 때 factory 객체를 사용해 client에서 어떻게 고양이와 개와 같은 객체를 구현하는지 알 필요 없게 캡슐화 시킵니다. 따라서 client는 factory 객체에게 고양이를 생성하라,개를 생성하라 라는 메시지만 던져주면 됩니다. (what만 넘기고 how는 전달하지 않게 되죠.)

Code

Tree Structure

Factory
 - Animal
 - Cat
 - Dog
 - Main

image-20220417140227121

Animal.java

abstract class를 생성해서 개(Dog), 고양이(Cat)이 상속(extends) 할 수 있도록 구현해 보았습니다.

public abstract class Animal {
    public void speak() {
        System.out.println("짖는다.");
    }
}

Dog.java, Cat.java

Animal이라는 abstract class를 상속받는 두 class를 구현했습니다.

public class Dog extends Animal{
    @Override
    public void speak() {
        System.out.println("Bark");
    }
}
public class Cat extends Animal {
    @Override
    public void speak() {
        System.out.println("Meow");
    }
}

AnimalType.java

public enum AnimalType{
  CAT("cat"), DOG("dog"), NONE("none");

  private final String value;
  animalType(String value) {
    this.value = value;
  }
  public String getValue(){
    return value;
  }

}

ClassObject

AnimalFactory class를 생성 후 factory 객체를 호출해서 사용합니다.

AnimalFactory.java

public class AnimalFactory {
    public Animal create(AnimalType type){
        if("cat".equals(type.getValue())){
            return new Cat();
        }else if("dog".equals(type.getValue())){
            return new Dog();
        }else {
            return new Animal() {
                @Override
                public void speak() {
                    super.speak();
                }
            };
        }
    }
}

Main.java

 AnimalFactory animalFactory = new AnimalFactory();
        Animal cat = animalFactory.create(AnimalType.CAT);
        cat.speak();
        Animal dog = animalFactory.create(AnimalType.DOG);
        dog.speak();
        Animal animal = animalFactory.create(AnimalType.NONE);
        animal.speak();

이렇게 client는 factory 내부에 어떻게 구현되어 있는지 알 필요 없이 cat 객체를 생성하라message만을 넘기면 됩니다.

Function

함수형으로 구현을 해 보았습니다. java에서는 Class로 대부분 표현합니다만... class와 fn형태가 있다고 해서 억지스럽게라도 한번 구현해 보았습니다.(호출 부분에 FactoryFn이라는 메소드를 생성한 것 뿐입니다...)

Main.java

해당 부분에서 호출과 FactoryMethod()라는 메소드를 생성해서 함수처럼 구현해 보았습니다.

input을 String으로 받을 경우와 enum으로 받을 경우로 나누어 보았습니다. 보통 구현 시 enum으로 구현하는것을 권장합니다.

public class Main {
  /*
      input을 String으로 받았을 경우
  */
    public Animal FactoryFn(String str){
        if("cat".equals(str)){
            new Cat().speak();
        } else if ("dog".equals(str)) {
            new Dog().speak();
        } else{
            return new Animal() {
                @Override
                public void speak() {
                    super.speak();
                }
                };
        }
    }
    public static void main(String[] args) {
                Main run = new Main();
        Animal cat = run.FactoryFn("cat");
        cat.speak();
        Animal dog = run.FactoryFn("dog");
        dog.speak();
        Animal animal = run.FactoryFn("none");
        animal.speak();
    }

  /*
      input을 enum으로 받았을 경우(prefer)
  */
   public Animal FactoryFn(AnimalType type){
        if(("cat").equals(type.getValue())){
            return new Cat();
        } else if (("dog").equals(type.getValue())) {
            return new Dog();
        } else{
            return new Animal() {
                @Override
                public void speak() {
                    super.speak();
                }
            };
        }
    }

    public static void main(String[] args) {
        Main run = new Main();

        Animal cat = run.FactoryFn(AnimalType.CAT);
        cat.speak();
        Animal dog = run.FactoryFn(AnimalType.DOG);
        dog.speak();
        Animal animal = run.FactoryFn(AnimalType.NONE);
        animal.speak();
    }
}

Result

image-20220417143035911

결과가 잘 출력되는 것을 알 수 있습니다.

factory 패턴은 factory methood, singleton, builder등 다양한 패턴에서 기본적으로 사용된다고 하여 한번 정리해 보았습니다.

긴 글 읽어 주셔서 감사합니다. 혹여 해당 글이 저작권 문제가 된다면 바로 조치하도록 하겠습니다.

References

추상클래스, 추상메서드

https://limkydev.tistory.com/188

factory pattern

https://www.youtube.com/watch?v=AmwEIt0vhxA

728x90
반응형