티스토리 뷰

 Python으로 구현한 팩토리 메소드에 이어 구현 내용을 이어서 Objective-c에서 추상 팩토리를 구현해보았습니다. Objective-c에서는 추상의 개념은 없지만 Protocol을 사용하여 java의 인터페이스를 구현할 수 있습니다. 전체적인 소스코드는 링크를 통해 걸어두도록 하겠습니다.

 단순히 공부하면서 짠 소스코드입니다.


Python으로 구현한 Factory Method Pattern

 http://www.thdev.net/320


구현 내용

 커피 가맹점에서 판매하는 커피의 종류가 다양하고, 가격도 모드 다릅니다. 커피의 이름과 가격은 가맹점의 위치에 따라서 변경이 가능합니다. aCafe의 위치는 사람이 적고, 학생들이 많이 모여있는 곳입니다. bCafe는 번화가에 차려진 카페입니다. 그에 따라 가격 조정이 필요한 가맹점입니다.

 - 추가 내용

 aCafe에서 커피를 구매하면 케이크를 함께 주는 서비스를 시작했습니다. 반응이 좋아 본사에서 직접 모든 가맹점들에게 유통할 수 있는 구조를 만들려고 합니다.

 이를 위해 본사에서는 커피와 케이크를 함께 판매하기로 하고, 케이크의 제료를 제공하기로 하였습니다. 케이크의 제료로 지역의 특성을 살릴 수 있도록 포도와 딸기를 제공하고, 2가지 크림으로 생크림과 버터크림을 제공하기로 하였습니다. 최종 완성품은 포도 버터크림 케이크와 딸기 생크림 케이크입니다.


팩토리 메소드 패턴 다이어그램

 아래가 Python에서 작성했던 다이어그램입니다. 이번에는 여기에 Protocol을 사용하여 추상 팩토리를 구현해보겠습니다.

 CafeStore와 Coffee가 있습니다.

 CafeStore에서는 주문 들어온 커피의 종류를 구분하는 팩토리메소드 aCafe와 bCafe가 있습니다.

 커피는 가격과 이름정보를 가지며, 커피의 종류는 5개로 구분하였습니다. 아이스커피, 아이스커피 화이트 밀크, 핫초코, 커피, 에스프레소 입니다. 이 이름들은 클래스의 이름이지 실제 이름은 가맹점마다 다르게 동작합니다.


- 추가 패턴 다이어그램

 추가로 Cream과 Decoration을 인터페이스로 작성하는 다이어 그램입니다. 각 카페의 특성에 따라서 크림과 데코레이션을 선택하여 케이크를 제조하는 방법을 사용하였습니다.

- 전체 패턴 다이어그램

 전체 다이어그램은 아래와 같습니다.

소스코드

 팩토리 패턴의 특성상 중복되는 코드가 많아질 수밖에 없습니다. 위에서 보이는 커피의 종류와 aCafe, bCafe의 종류에따라 커피의 종류를 각 5개씩 작성해야 합니다. 그래서 총 10개의 클래스가 작성되어야 합니다. 그리고 이번 Objective-c에서 작성한 팩토리 패턴은 위에서 보는 하단의 CafeCakeIngredientFactory 부분을 작성하기 위한 코드입니다. 일부분의 코드만 아래에 나열하도록 하겠습니다.


CafeCakeIngredientFactory Protocol 구현

#import <Foundation/Foundation.h>

@class CreamProtocol;
@class DecorationProtocol;
@protocol CafeCakeIngredientFactory <NSObject>
-(NSString *)makeCream;
-(NSString *)makeDecoration;
@end


aCafeCakeIngredientFactory.h 구현

#import <Foundation/Foundation.h>
#import "CafeCakeIngredientFactory.h"

@interface aCafeCakeIngredientFactory : NSObject <CafeCakeIngredientFactory>
-(NSString *)makeCream;
-(NSString *)makeDecoration;

@end


aCafeCakeIngredientFactory.m 구현

#import "aCafeCakeIngredientFactory.h"
#import "WhippedCream.h"
#import "Strawberry.h"

@implementation aCafeCakeIngredientFactory
-(NSString *)makeCream {
    return [[WhippedCream new] getCream];
}
-(NSString *)makeDecoration {
    return [[Strawberry new] getDecoration];
}

@end


CreamProtocol.h 구현

#import <Foundation/Foundation.h>

@protocol CreamProtocol <NSObject>
-(NSString *)getCream;
@end


WhippedCream.h 구현

#import <Foundation/Foundation.h>
#import "CreamProtocol.h"

@interface WhippedCream : NSObject <CreamProtocol>
-(NSString *)getCream;
@end

기존 소스코드에서 수정

 기존 소스코드에서의 수정이긴 하지만 Python에서 구현했던 팩토리 패턴을 가지고와서 구현하였기에 새롭게 추가되는 부분등만 간단히 살펴보고 넘어가겠습니다.


aCafeIcedCoffee.h

 각 커피 클래스에 아래와 같은 코드를 변경해야 합니다. 제가 모든 코드를 init을 통해 new를 할 수 있도록 작성하였습니다.

#import "Coffee.h"
#import "CafeCakeIngredientFactory.h"

@interface aCafeIcedCoffee : Coffee
-(id)init:(id)cif;
@end


aCafeIcedCoffee.m

 케이크 주문시 해당 원료들을 가지고와서 케이크를 만들 수 있게 합니다. 이를 위해 cream과 decoration을 불러옵니다.

#import "aCafeIcedCoffee.h"

@implementation aCafeIcedCoffee
-(id)init:(id)cif {
    if([super init] == self) {
        self.price = 4000;
        self.name = @"aCafe Iced Coffee";
        self.cream = [cif makeCream];
        self.decoration = [cif makeDecoration];
    }
    return self;
}
@end

aCafe.m

 모든 커피를 생성할 때 위에서 작성한 init 메소드에 케익을 호출할 수 있도록 아래와 같이 변경합니다.

@implementation aCafe
-(Coffee *)makeCoffee:(int)order {
    if(order == 0) {
        return [[aCafeCoffee new] init:[aCafeCakeIngredientFactory new]];
    } else if(order == 1) {
        return [[aCafeIcedCoffee new] init:[aCafeCakeIngredientFactory new]];
    } else if(order == 2) {
       return [[aCafeicedCoffeeWithMilk new] init:[aCafeCakeIngredientFactory new]];
    } else if(order == 3) {
        return [[aCafeHotChocolate new] init:[aCafeCakeIngredientFactory new]];
    } else if(order == 4) {
        return [[aCafeEspresso new] init:[aCafeCakeIngredientFactory new]];
    }
    return NULL;
}
@end

Coffee.m

 최종적으로 출력하는 getCoffee에 decoration과 cream을 불러와 출력하게 됩니다.

#import "Coffee.h"
#import "CafeCakeIngredientFactory.h"

@implementation Coffee
@synthesize name;
@synthesize price;
@synthesize cream;
@synthesize decoration;

-(void)getCoffee {
    NSLog(@"Coffee Name : %@, Price : %d", self.name, self.price);
    NSLog(@"%@ %@ cake", self.decoration, self.cream);
}
@end

결과 화면


마무리

 간단히 구현내용과 함께 작성한 추상 팩토리입니다. 실제로 Objective-c에서는 추상이라는 개념은 없지만 Protocol을 활용하여 동일한 코드를 작성할 수 있었습니다. 실제로 이 팩토리 패턴을 어디에서 적용해야 할지는 의문이긴 합니다. 위와 같은 코드를 작성하기 위해서 저는 커피가 각 카페마다 5개 * 2 = 10개의 커피를 적용하였고, 제품군을 구분하기 위해서 추상 팩토리를 추가하여 크림과 데코레이션을 구분하였습니다. 너무 많은 클래스를 사용한다는 생각이 들기도 합니다.

 혹시 틀린 부분이나 잘못된 부분은 지적부탁드립니다. - 더보기를 누리시면 샘플 코드 다운 받을 수 있습니다.





댓글