안녕 친구! 오늘도 우리는 계속해서 여러분과 함께 디자인 패턴을 공부할 것입니다. 이번 강의에서는 공장(Factory)에 대해 이야기하겠습니다. 이 템플릿을 사용하여 어떤 문제가 해결되는지 논의하고 공장이 커피숍을 여는 데 어떻게 도움이 되는지 예시를 살펴보겠습니다. 그리고 공장을 만드는 간단한 5단계도 알려드리겠습니다. 모든 사람과 같은 생각을 갖고 본질을 쉽게 파악하려면 다음 주제를 잘 알고 있어야 합니다.
- Java의 상속
- Java에서 참조 유형 축소 및 확장
- 다양한 클래스와 객체 간의 상호 작용
공장이란 무엇입니까?
Factory 디자인 패턴을 사용하면 객체 생성을 제어할 수 있습니다. 새로운 객체를 생성하는 과정은 그렇게 간단하지도, 그렇다고 너무 복잡하지도 않습니다. 우리 모두는 새로운 객체를 생성하려면new
. 그리고 여기서는 관리할 것이 아무것도 없는 것처럼 보일 수도 있지만 그렇지 않습니다. 애플리케이션에 후손이 많은 특정 클래스가 있고, 조건에 따라 특정 클래스의 인스턴스를 생성해야 하는 경우 문제가 발생할 수 있습니다. Factory는 조건에 따라 다른 객체를 생성하는 문제를 해결하는 데 도움이 되는 디자인 패턴입니다. 추상적이지 않나요? 아래 예를 보면 더 구체적이고 명확해질 것입니다.
우리는 다양한 종류의 커피를 만듭니다
커피숍을 자동화하고 싶다고 가정해 보겠습니다. 우리는 다양한 종류의 커피를 준비하는 방법을 배워야 합니다. 이를 위해 애플리케이션에서 커피 클래스와 그 파생 상품인 아메리카노, 카푸치노, 에스프레소, 라떼(우리가 준비할 커피 유형)를 만듭니다. 일반 커피 수업부터 시작하겠습니다.public class Coffee {
public void grindCoffee(){
// перемалываем кофе
}
public void makeCoffee(){
// делаем кофе
}
public void pourIntoCup(){
// наливаем в чашку
}
}
다음으로 상속자를 생성해 보겠습니다.
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
고객은 특정 유형의 커피를 주문할 것이며 이 정보는 프로그램에 전달되어야 합니다. 예를 들어 를 사용하는 등 다양한 방법으로 이 작업을 수행할 수 있습니다 String
. 그러나 이러한 목적에 가장 적합합니다 enum
. enum
주문을 수락하는 커피 유형을 생성하고 정의해 보겠습니다 .
public enum CoffeeType {
ESPRESSO,
AMERICANO,
CAFFE_LATTE,
CAPPUCCINO
}
좋습니다. 이제 커피숍의 코드를 작성해 보겠습니다.
public class CoffeeShop {
public Coffee orderCoffee(CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new Americano();
break;
case ESPRESSO:
coffee = new Espresso();
break;
case CAPPUCCINO:
coffee = new Cappucсino();
break;
case CAFFE_LATTE:
coffee = new CaffeLatte();
break;
}
coffee.grindCoffee();
coffee.makeCoffee();
coffee.pourIntoCup();
System.out.println("Вот ваш кофе! Спасибо, приходите еще!");
return coffee;
}
}
이 방법은 orderCoffee
두 가지 구성 요소로 나눌 수 있습니다.
- 블록에 특정 커피 인스턴스를 생성합니다
switch-case
. 여기서는 Factory가 수행하는 작업이 조건에 따라 특정 유형을 생성하는 것입니다. - 준비 자체는 갈아서 요리하고 컵에 붓는 것입니다.
- 준비 알고리즘 자체(갈기, 요리하기, 컵에 따르기)는 변경되지 않고 그대로 유지됩니다(적어도 그러기를 바랍니다).
- 그러나 커피의 범위는 바뀔 수 있습니다. 아마도 우리는 모카를 만들기 시작할 것입니다.. 모카.. 모카치... 신의 축복이 있기를, 새로운 종류의 커피입니다.
switch-case
. orderCoffee
우리 커피숍에서는 이 방법이 다양한 종류의 커피를 만드는 유일한 장소가 아닐 수도 있습니다 . 따라서 여러 곳에서 변경이 이루어져야 합니다. 당신은 아마도 내가 무엇을 얻고 있는지 이미 이해하고 있을 것입니다. 우리는 리팩터링이 필요합니다. 두 가지 이유로 커피 생성을 담당하는 블록을 별도의 클래스로 이동합니다.
- 우리는 커피를 만드는 논리를 다른 곳에서도 재사용할 수 있을 것입니다.
- 범위가 변경되면 커피 생성이 사용될 모든 곳에서 코드를 편집할 필요가 없습니다. 한 곳에서만 코드를 변경하면 충분합니다.
우리는 첫 번째 공장을 톱질하고 있습니다
이를 위해 커피 클래스의 필요한 인스턴스 생성만 담당하는 새 클래스를 생성해 보겠습니다.public class SimpleCoffeeFactory {
public Coffee createCoffee (CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new Americano();
break;
case ESPRESSO:
coffee = new Espresso();
break;
case CAPPUCCINO:
coffee = new Cappucino();
break;
case CAFFE_LATTE:
coffee = new CaffeLatte();
break;
}
return coffee;
}
}
축하해요! 우리는 가장 간단한 형태로 Factory 디자인 패턴을 구현했습니다. 메서드를 정적으로 만들면 모든 것이 더 간단해질 수 있습니다 createCoffee
. 하지만 그렇게 되면 두 가지 가능성을 잃게 됩니다.
- 에서 상속
SimpleCoffeeFactory
하고 재정의합니다createCoffee
. - 우리 클래스에서 필요한 팩토리 구현을 구현합니다.
커피숍에 공장을 도입하다
팩토리를 사용하여 커피숍 클래스를 다시 작성해 보겠습니다.public class CoffeeShop {
private final SimpleCoffeeFactory coffeeFactory;
public CoffeeShop(SimpleCoffeeFactory coffeeFactory) {
this.coffeeFactory = coffeeFactory;
}
public Coffee orderCoffee(CoffeeType type) {
Coffee coffee = coffeeFactory.createCoffee(type);
coffee.grindCoffee();
coffee.makeCoffee();
coffee.pourIntoCup();
System.out.println("Вот ваш кофе! Спасибо, приходите еще!");
return coffee;
}
}
엄청난. 이제 Factory 디자인 패턴의 구조를 개략적이고 간결하게 설명해 보겠습니다.
자신의 공장을 여는 5단계
1단계. 프로그램에는 아래 그림과 같이 여러 하위 항목이 있는 클래스가 있습니다. 2단계 . 각 하위 클래스에 대해 열거형 변수를 정의하는 클래스를 만듭니다 .enum
enum CatType {
LION,
TIGER,
BARSIK
}
3단계. 공장을 건설합니다. 라고 부르면 MyClassFactory
코드는 아래와 같습니다.
class CatFactory {}
4단계. 공장에서 createMyClass
변수를 사용하는 메서드를 만듭니다 enum
MyClassType
. 아래 코드:
class CatFactory {
public Cat createCat(CatType type) {
}
}
switch-case
5단계 . 모든 열거형 값을 반복하고 해당 enum
값 에 해당하는 클래스의 인스턴스를 생성하는 메서드 본문에 블록을 작성합니다 .
class CatFactory {
public Cat createCat(CatType type) {
Cat cat = null;
switch (type) {
case LION:
cat = new Barsik();
break;
case TIGER:
cat = new Tiger();
break;
case BARSIK:
cat = new Lion();
break;
}
return cat;
}
}
상사처럼.
GO TO FULL VERSION