[디자인 패턴] 팩토리 패턴

Narcoker·2023년 8월 1일
0

디자인 패턴

목록 보기
4/8

팩토리 패턴

생성 패턴 중 하나로
생성 로직을 캡슐화하여 클라이언트 코드에서 직접 객체를 생성하지 않도록 하는 것이 목표이다.

즉, 객체의 생성 코드를 별도의 클래스/메서드로 분리함으로써
객체 생성의 변화에 대비하는 데 유용하다.

단순 팩토리 패턴(Simple Factory Pattern)

단순 팩토리는 클래스가 아니라 메소드다.
이 메소드는 클라이언트가 전달한 인자를 바탕으로 다양한 유형의 객체를 생성하고 반환한다.

abstract class Vehicle {
    abstract void drive();
}

class Car extends Vehicle {
    void drive() {
        System.out.println("Driving a car");
    }
}

class Truck extends Vehicle {
    void drive() {
        System.out.println("Driving a truck");
    }
}

class VehicleFactory {
    Vehicle createVehicle(String type) {
        if (type.equals("car")) {
            return new Car();
        } else if (type.equals("truck")) {
            return new Truck();
        }
        return null;
    }
}

public class Main {
    public static void main(String[] args) {
        VehicleFactory factory = new VehicleFactory();

        Vehicle car = factory.createVehicle("car");
        car.drive(); // Outputs: 'Driving a car'

        Vehicle truck = factory.createVehicle("truck");
        truck.drive(); // Outputs: 'Driving a truck'
    }
}

문제점

팩토리 패턴의 단점은 팩토리 클래스 내에서 새로운 클래스를 추가하거나 제거할 때마다
if-else나 switch-case 조건문을 수정해야 한다는 것이다.

이는 OCP(Open-Closed Principle)를 위반하게 된다.
OCP는 소프트웨어 개체(클래스, 모듈, 함수 등)는 확장에는 열려 있어야 하고,
수정에는 닫혀 있어야 한다는 원칙이다.

팩토리 메서드 패턴(Factory Method Pattern)

인터페이스를 통해 객체를 생성하지만, 실제 생성 로직은 서브클래스에서 담당한다.
이렇게 하면 클라이언트는 사용하는 객체의 클래스를 직접 알 필요가 없다.

팩토리 메서드 패턴에서는 객체 생성을 서브 클래스에 위임하므로
새로운 유형의 객체를 추가하려면 단순히 새로운 서브 클래스를 만들고,
해당 클래스의 팩토리 메서드를 오버라이드 하면 된다.

이렇게 하면 클라이언트 코드를 변경하지 않고도 새로운 유형의 객체를 생성할 수 있게 된다.

즉, OCP 원칙을 지킬 수 있다.

abstract class Vehicle {
    abstract void drive();
}

class Car extends Vehicle {
    void drive() {
        System.out.println("Driving a car");
    }
}

class Truck extends Vehicle {
    void drive() {
        System.out.println("Driving a truck");
    }
}

abstract class VehicleFactory { // 인터페이스 역할
    abstract Vehicle createVehicle();
}

class CarFactory extends VehicleFactory { // 생성 로직이 존재하는 인터페이스의 서브 클래스
    Vehicle createVehicle() {
        return new Car();
    }
}

class TruckFactory extends VehicleFactory { // 생성 로직이 존재하는 인터페이스의 서브 클래스
    Vehicle createVehicle() {
        return new Truck();
    }
}

public class Main {
    public static void main(String[] args) {
        VehicleFactory carFactory = new CarFactory();
        Vehicle car = carFactory.createVehicle();
        car.drive(); // Outputs: 'Driving a car'

        VehicleFactory truckFactory = new TruckFactory();
        Vehicle truck = truckFactory.createVehicle();
        truck.drive(); // Outputs: 'Driving a truck'
    }
}

팩토리 메서드 패턴의 단점은 각 객체를 위한 팩토리 메서드를 각각 제공해야 한다는 것이다.

이는 단일 팩토리 클래스가 많은 수의 팩토리 메서드를 가지게 되는 문제를 야기할 수 있다.

추상 팩토리 패턴(Abstract Factory Pattern)

팩토리 메소드 패턴을 확장한 것으로,
각각 다른 종류의 관련 객체들을 생성하는 팩토리 메소드의 그룹을 제공한다.

추상 팩토리 패턴에서는 관련된 객체의 그룹을 생성하는 인터페이스 를 제공한다.
따라서 각 팩토리는 특정 "패밀리"의 객체를 생성하며,
클라이언트는 필요한 팩토리를 사용하여 관련된 객체들을 생성할 수 있다.

이렇게 하면 한 팩토리 클래스가 너무 많은 책임을 갖는 것을 방지하고
객체 생성의 책임을 분산시킬 수 있다.

Animal 관련 객체도 필요하다고 가정한 코드 이다.

// Vehicle
class Vehicle {
  drive() {}
}

class Car extends Vehicle {
  drive() {
    return "Driving a car";
  }
}

class Truck extends Vehicle {
  drive() {
    return "Driving a truck";
  }
}

// Animal
class Animal {
  speak() {}
}

class Dog extends Animal {
  speak() {
    return "Woof!";
  }
}

class Cat extends Animal {
  speak() {
    return "Meow!";
  }
}

class VehicleFactory { // Vehicle과 관련된 객체의 그룹을 생성하는 인터페이스
  createCar() {
    throw new Error("This method should be overridden");
  }

  createTruck() {
    throw new Error("This method should be overridden");
  }
}

class AnimalFactory { // Animal과 관련된 객체의 그룹을 생성하는 인터페이스
  createDog() {
    throw new Error("This method should be overridden");
  }

  createCat() {
    throw new Error("This method should be overridden");
  }
}

class ConcreteVehicleFactory extends VehicleFactory { // Vehicle 객체를 생성하는 팩토리
  @Override
  createCar() {
    return new Car();
  }
  @Override
  createTruck() {
    return new Truck();
  }
}

class ConcreteAnimalFactory extends AnimalFactory { // Animal 객체를 생성하는 팩토리
  createDog() {
    return new Dog();
  }

  createCat() {
    return new Cat();
  }
}

const factory = new ConcreteVehicleFactory();
const car = factory.createCar();
console.log(car.drive()); // Outputs: 'Driving a car'
const truck = factory.createTruck();
console.log(truck.drive()); // Outputs: 'Driving a truck'

const animalFactory = new ConcreteAnimalFactory();
const dog = animalFactory.createDog();
console.log(dog.speak()); // Outputs: 'Woof!'
const cat = animalFactory.createCat();
console.log(cat.speak()); // Outputs: 'Meow!'
profile
열정, 끈기, 집념의 Frontend Developer

0개의 댓글