Developer/Pattern

[Object-c]FactoryPattern - 팩토리 패턴

블로blow 2016. 4. 19. 09:38
728x90

(소스 주소 : https://github.com/minjoongkim/iOS-Pattern)



팩토리 패턴이란?

객체 생성을 처리하는 패턴입니다. 


어떠한 경우에 사용하는가?

예를들어 책이라는 클래스가 있고, 

그 하위에 만화책, 소설책이라는 클래스가 있습니다.


만화책, 소설책은 책이라는 큰 범위안에 각자가 해야할 메소드들이 따로 있습니다.


어떠한 정보를 받아서 클래스로 생성할때, 매번 if문으로 만화책인지 소설책인지 판단해서 클래스를 만들게 되면 번거롭고 틀릴수도 있기 때문에 이 부분을 띄어서(나눠서) 팩토리 메소드를 만들게 됩니다.

그렇게 되면 객체를 생성할때마다 팩토리 메소드에 객체생성을 하도록 지시하면 객체를 생성해서 반환하게 됩니다.



팩토리 패턴을 사용하게 되면?

이렇게 되면, 객체생성의 버그를 줄일수 있고 유연성을 증가시킬수 있습니다.



우선 book 클래스와 하위 클래스를 먼저 살펴보겠습니다.


부모가 될 Book 클래스


Book.h

#import <Foundation/Foundation.h>


@interface Book : NSObject {

    NSString *name;

    int price;

    NSString *category;

}


-(void)setName:(NSString*)bookName;

-(NSString*)getName;

-(void)setPrice:(int)bookprice;

-(int)getPrice;

-(void)setCategory:(NSString*)bookCategory;

-(NSString*)getCategory;

-(void)bookInfo;


@end


Book.m

#import "Book.h"


@implementation Book


-(void)setName:(NSString*)bookName {

    name = bookName;

}

-(NSString*)getName {

    return name;

}

-(void)setPrice:(int)bookprice {

    price = bookprice;

}

-(int)getPrice {

    return price;

}


-(void)setCategory:(NSString*)bookCategory {

    category = bookCategory;

}

-(NSString*)getCategory {

    return category;

}


-(void)bookInfo {

    NSLog(@"%@ : %@ book price is %d", category, name, price);

}


@end



Book 클래스의 하위 클래스 ComicBook


ComicBook.h


#import <Foundation/Foundation.h>

#import "Book.h"

@interface ComicBook : Book


-(id)init:(NSString*)bookName price:(int)bookprice;

@end



ComicBook.m


#import "ComicBook.h"


@implementation ComicBook


-(id)init:(NSString*)bookName price:(int)bookprice {

    self = [super init];

    if (self) {

        [self setName:bookName];

        [self setPrice:bookprice];

        [self setCategory:@"Comic"];

    }

    return self;

}


@end



Book 클래스의 하위 클래스 NovelBook


NovelBook.h


#import <Foundation/Foundation.h>

#import "Book.h"

@interface NovelBook : Book

-(id)init:(NSString*)bookName price:(int)bookprice;

@end



NovelBook.m


#import "NovelBook.h"


@implementation NovelBook


-(id)init:(NSString*)bookName price:(int)bookprice {

    self = [super init];

    if (self) {

        [self setName:bookName];

        [self setPrice:bookprice];

        [self setCategory:@"Novel"];

    }

    return self;

}


@end



이제 이 클래스들을 이용해 객체를 생성해보겠습니다.


팩토리 패턴 없이 객체를 생성할 때,


Book *book;

NSString *bookCategory = @"Comic";

if([bookCategory isEqualToString:@"Comic"]) {

    book = [[ComicBook alloc]init:@"SlamDunk" price:5000];

}else if([bookCategory isEqualToString:@"Novel"]) {

    book = [[NovelBook alloc]init:@"HarryPotter" price:13000];

}


[book bookInfo];


만약 Book을 상속받는 클래스가 많다면 코드마다 판단해서 객체를 넣기엔 너무나 많은 조건문이 들어가고, 

객체 생성하는 부분이 한군데가 아니라면 그 모든곳을 다 고쳐줘야 하는 번거로움이 있고, 가독성이 떨어집니다.


그래서 이번엔 팩토리 클래스를 만들고 객체를 생성해보겠습니다.



팩토리 클래스 BookFactory


BookFactory.h


#import <Foundation/Foundation.h>

#import "Book.h"


@interface BookFactory : NSObject

+(Book*)makeBook:(NSString*)bookType name:(NSString*)bookName price:(int)bookPrice;

@end


BookFactory.m


#import "BookFactory.h"

#import "NovelBook.h"

#import "ComicBook.h"


@implementation BookFactory


+(Book*)makeBook:(NSString*)bookType name:(NSString*)bookName price:(int)bookPrice{

    if([bookType isEqualToString:@"Comic"]) {

        return [[ComicBook alloc] init:bookName price:bookPrice];

    }else if([bookType isEqualToString:@"Novel"]) {

        return [[NovelBook alloc] init:bookName price:bookPrice];

    }else {

        return nil;

    }

}


@end



팩토리 패턴으로 객체를 생성할 때,


Book *bookUseFactoryComic = [BookFactory makeBook:@"Comic" name:@"SlamDunk" price:5000];

[bookUseFactoryComic bookInfo];


Book *bookUseFactoryNovel = [BookFactory makeBook:@"Novel" name:@"HarryPotter2" price:13000];

[bookUseFactoryNovel bookInfo];


조건문으로 객체를 생성하던 부분이 클래스로 빠져나가서 객체생성을 캡슐화하고 유연성을 증가 시킬수 있습니다.



728x90

'Developer > Pattern' 카테고리의 다른 글

iOS 아키텍처 VIPER  (1) 2018.06.22
[Object-c]DecoratorPattern - 데코레이터 패턴  (0) 2016.04.20