A2공간 - 도움되는 글을 쓰자

ani2life.egloos.com

포토로그 마이가든


그냥 잡담

※방명록은 따로 없고 무조건 최신글에 댓글 남기시면 됩니다. ^^

위드블로그


올블로그 올블릿


Factory Method 패턴과 Abstract Factory 패턴의 차이점 개발/플밍

Factory Method & Abstract Factory 차이점


작성자 : 박민권

Factory Method 패턴과 Abstract Factory 패턴이 너무 비슷해 보여서 이 두 패턴의 차이점을 정의해봅니다.
두 패턴에 대한 자세한 내용은 이곳에 기술하지 않습니다.
디자인 패턴에 대해 궁금증을 갖고 이 글을 읽으시는 분이라면 상속, 다형성, abstract등 클래스에 대한 기본지식은 알고 있다는 가정하에 글을 작성했습니다.
이해하기 쉽도록 스타크래프트를 예로 설명하겠습니다.
틀린 부분이 있다면 지적 부탁드립니다.

Factory Method



abstract class 유닛{
    void 어택();
}

class 마린 : 유닛{
    void 어택(){총쏜다;}
}

class 매딕 : 유닛{
    void 어택(){치료한다;}
}

class 배럭{
    유닛 생성(종류){return (종류==MR) ? new 마린 : new 매딕;}
}


배럭(클래스)에서는 유닛(추상클래스)을 생성할 수 있습니다.
유닛을 상속받은 마린(클래스)과 매딕(클래스)이 있습니다.
배럭의 생성() 메소드에 인수로 무엇을 주느냐에 따라 마린 또는 매딕을 생성할 수 있습니다.

이런 복잡해 보이는 방식을 어디다가 쓰려고 만들었을까요?
아래와 같은 장점이 있기 때문입니다.


유닛 H;
H = 배럭.생성(MR); //마린생성
H.어택(); //총쏘기

H = 배럭.생성(MD); //매딕생성
H.어택(); //치료하기


배럭에서는 상황에 따라 마린 또는 매딕이 생성되지만 무엇이 생성되었는지는 알지 못해도 생성된 유닛을 사용하는데는 문제가 없습니다.
이렇듯 Factory에서 생성된 객체를 사용자는 종류에 신경쓰지 않고 생성된 객체를 똑같이 사용할 수 있습니다.

Abstract Factory



abstract class 유닛{
    void 어택();
}

class 마린 : 유닛{
    void 어택(){총쏜다;}
}

class 매딕 : 유닛{
    void 어택(){치료한다;}
}

class 배틀크루저 : 유닛{
    void 어택(){레이저;}
}

class 레이스 : 유닛{
    void 어택(){미사일;}
}

abstract class 생산공장{
    유닛 생산();
}

class 배럭 : 생산공장{
    유닛 생성(종류){return (종류==MR) ? new 마린 : new 매딕;}
}

class 스타포트 : 생산공장{
    유닛 생성(종류){return (종류==BC) ? new 배틀크루저 : new 레이스;}
}


제가 찾아본 Abstract Factory 패턴에 대한 예제는 가상공장에서 가상제품1과 가상제품2를 생산하는 메소드가 나뉘어져 있는데 그 부분이 중요한 것이 아니라는 판단이 들어 제 나름대로 예제를 작성해 봤습니다.

Abstract Factory 패턴에 대한 장점은 Factory Method 패턴에 대한 장점의 확장이라 할 수 있겠습니다.
위 클래스를 이용한 예제는 아래와 같습니다.


생산공장 F;
유닛 H;

F = new 배럭();
H = F.생성(MR); //마린생성
H.어택(); //총쏘기

F = new 스타포트();
H = F.생성(BC); //배틀크루저생성
H.어택(); //레이저


* 마음대로 퍼가셔도 되지만 출처를 남겨주세요.(요즘 워낙 불펌이 많아서요.)

김재호// 추가 설명 감사합니다.
이 패턴을 설명하는 다른 사이트의 설명과 맞추어 설명하기 위해 H = F.생성(MR); 식으로 생성했으며 아래 댓글로 달린 김재호님의 추가 설명도 같이 참고하시기 바랍니다.

태그 :

트랙백

이 글과 관련된 글 쓰기 (트랙백 보내기)
TrackbackURL : http://ani2life.egloos.com/tb/2887675 [도움말]

핑백

덧글

  • daybreaker 2006/12/21 01:25 # 삭제 답글

    흠.. 디자인 패턴이라는 게 이런 것들을 설명하는 건가요?
    그냥 전 당연하게(....) 사용했던 것들에도 이름이 붙어있었군요. -.-; (아직 디자인패턴 책을 제대로 본 적이 없어서...)
  • -A2- 2006/12/21 03:14 # 답글

    daybreaker// 네 디자인패턴이란게 이런 것들에 이름을 붙여놓은 것이죠.
    대부분 프로그램을 많이 짜본 사람들은 한번씩은 고민하고 구현해 봤던 것들입니다.

    자기 나름대로 고민해서 알고리즘과 설계를 구현했는데 알고보니 자신이 구현한 것과 똑같은 것이 이름까지 붙어서 떡 하니 나와있을때가 있습니다.
    그런데 저는 그럴때가 참 재밌게 느껴집니다.
    선구자들이 밟은 길을 나도 밟았구나 싶어서요.

    프로그램을 많이 설계해본 사람에게 디자인패턴에 대한 공부는 불필요한 느낌이 들지도 모르지만 다른 개발자들과 대화하거나 코드에 대한 설명시 패턴용어를 사용함으로 장점이 있지 않을까 싶습니다.

    저도 이번에 디자인 패턴책 하나 구입했는데 소설읽듯이 쭉~ 읽어볼 생각입니다.
  • daybreaker 2006/12/23 17:31 # 삭제 답글

    네, 확실히 다른 사람과 의사소통할 때 일관된 용어를 사용하는 것이 중요하겠지요.
    그런 면에서 공부는 해두어야겠죠. ^^;
  • 임성현 2007/02/23 15:26 # 삭제 답글

    설명이 쏙 들어오네요..잘보고 가요,,
  • 김재호 2007/03/20 16:30 # 삭제 답글

    Abstract Factory를 설명하기 위해서는 다음의 예제가 필요할 것으로 보입니다.

    생산공장 F;
    유닛 H;

    F = new 배럭();
    H = F.생성(); //마린과 매딕 생성
    H.어택(); //총쏘기와 치료

    F = new 스타포트();
    H = F.생성(); //배틀크루저와 레이스의 생성
    H.어택(); //레이저와 미사일

    ----------------
    이렇게 factory 생성만 다르게 하고 나머지는 동일해야 factory를 무엇을 생성하느냐에 따라 기능이 달라진다는 설명이 됩니다. 이것이 abstract factory이고 factory method는 이렇게 하기 위한 한가지 방법이지요.
  • -A2- 2007/03/22 00:10 # 답글

    김재호// 추가 설명 감사합니다.
  • 깡통 2007/10/01 13:12 # 삭제 답글

    전 한가지 질문이 있는데요.. 지금 작성하신 Factory Method 에도 추상 Factory 가 있어야 하는 것 아닌가요? 제가 아는거하고 조금 내용이 다른 것 같은데..
  • -A2- 2007/10/01 19:49 # 답글

    깡통// Factory Method를 왜 사용하는지를 아는 것이 중요합니다.
    위는 예제는 Factory Method에 대한 하나의 예제일 뿐이며 다양한 방법으로 설계 및 구현 할 수 있습니다.
    Factory Method를 사용하는 사용자는 내부 설계가 어떻게 되었는지 알 필요가 없습니다.
    어떻게 구현하던 Factory Method의 역할에 충실하면 됩니다.

    그럼 Factory Method는 어떤 역할을 해야할까요?

    Factory Method를 호출하여 반환된 객체가 어떤 것인지 신경쓸 필요 없이 그냥 쓸 수 있습니다.
    JDBC에서 Connection객체를 얻을때도 그게 MySQL접속객체이던 Oracle접속객체이던 그 접속객체를 사용하는데 차이가 없습니다.
    이 글에서 설명하는 유닛도 마린객체이던 매딕객체이던 사용하는데 차이가 없습니다.

    뿐만 아니라 객체의 생성을 사용자가 직접 new를 이용해서 생성하는 것이 아니라 메소드를 통해 생성된 객체를 받는 것이기 때문에 객체를 생성하기 위해 내부적으로 복잡한 처리를 하더라도 사용자는 신경쓸 필요가 없습니다.

    사용자가 Factory Method를 호출해서 생성된 객체를 공통된 인터페이스를 통해서 무엇이 생성되었는지 신경쓰지 않고 동일하게 사용할 수 있으면 Factory Method의 필요성과 역할은 끝난것입니다.

    Factory Method를 제공하는 클래스의 구조는 신경쓸 필요가 없는 것입니다.
    클래스의 구조가 상속구조던 단일 클래스던 그건 사용자의 관심사가 아닙니다.
    사용자는 오직 Factory Method를 이용해서 자신이 원하는 객체를 생성해서 사용하는데 관심이 있습니다.

    한번 잘 생각해보시기 바랍니다.
    보통 JDBC 접속객체를 구하는 코드는 아래와 같습니다.
    // MySQL
    Class.forName("MySQL JDBC드라이버");
    Connect conn = DriverManager.getConnection("접속URL");

    // Oracle
    Class.forName("Oracle JDBC드라이버");
    Connect conn = DriverManager.getConnection("접속URL");

    위의 코드를 사용하면서 getConnection() 이라는 Factory Method를 제공하는 DriverManager 클래스의 구조를 신경쓰며 코딩하지는 않습니다.
    뿐만 아니라 Connect은 인터페이스인데 그렇다면 생성된 conn 객체가 사실은 어떤 클래스인지, 그 클래스의 구조가 어떤지 신경쓰지 않습니다.

    이렇듯 사용자는 클래스의 구조를 전혀 몰라도 Factory Method를 사용하고 있습니다.
    디자인 패턴 설명에 나오는 설계에 종속되지 마시고 각 디자인 패턴의 필요성과 설계방법을 이해하고 님의 것으로 만들면 책을 보지 않더라도 공부한 패턴 이상의 멋진 설계를 하실 수 있으실 겁니다.

    "여기에는 OOO패턴을 사용해야지"가 아니라 "어라! 만들고 보니 OOO패턴이네"가 되어야 합니다.
  • 나무귀신 2008/10/14 18:18 # 삭제 답글

    DriverManager는 내부적으로 Factory Method Pattern을 이용합니다.

    Driver가 Creater, OracleDriver가 ConcreateCreator가 됩니다.
    또한, Connection이 Product, OracleConnection이 ConcreateProduct가 됩니다.



    DriverManager class는 Connection 생성을 위한, 간략화된 Adapter정도로 보는게 맞을 거 같습니다.
  • 나무귀신 2008/10/14 18:21 # 삭제 답글

    그리고, Factory Method Pattern은 Creator Interface에서 생성method를 정의하고, 실제 생성은 Concreate Creator에서 이루어지는 것이니,
    첫번째 예제보다는, Abstract Factory Pattern에서 든 예제가 Factory Method Pattern에 맞는게 아닌가 하는 생각이 듭니다.

    Factory Method와 Abstract Factory는 항상 @,.@하게 만들어서..;
  • -A2- 2008/10/14 23:25 #

    Factory Method와 Abstract Factory 두개는 참 얽혀있는거 같아요.
  • 우나 2009/06/15 16:59 # 삭제 답글

    음 쉽고 간단한 설명 이네요 잘 읽고 갑니다
  • -A2- 2009/06/15 17:39 #

    도움이 되셨다니 기쁘네요. ^^
  • 최익필 2009/11/03 11:51 # 삭제 답글

    오랜만에 들렸습니다. 요즘 디자인 패턴(헤드 퍼스트) 책을 읽고 있는데, 책이 재미가 없어서 졸면서 보았습니다.
    그래서 인지 머리속에 그 개념이 안들어 오고 있었는데, 이 포스팅을 통해서 재미있게 읽었습니다.

    포스팅의 내용 외로 몇가지 추가하자면,

    팩토리 패턴( or 추상 팩토리 패턴 )의 사용 목적 중
    1. 이상한 방법으로 객체를 생성하는 것을 막기 위해서
    - 생성 객체의 생성자를 private 선언 후, friend로 팩토리 메소드만 접근할 수 있게 제한함
    - 즉, 배럭에서만 생성 될 수 있도록 강제 함

    2. 객체의 생성을 카운팅 하기 위해서
    - 예를 들어, 유닛의 총 갯수를 제한하기 위해서 입니다. 이럴 때는, delete 도 맵핑하여 제공해야 합니다.


    몇 가지 더 있을 것(더 이상은 모르겠습니다) 같은데, 현재는 이럴 경우에서 밖에 써보지 못했네요. : )

    그럼 수고하세요.
  • -A2- 2009/11/04 01:48 #

    추가 내용 감사드립니다. ^^
덧글 입력 영역