Factory Pattern


Factory Method Pattern


팩토리 패턴도 참 많이 쓰이는 패턴이다. 책과 인터넷을 한참 찾아보니 대부분 두 가지 형태로 혼용되어 사용되는 것 같다.  뭐 어차피 패턴이 쓰기 나름이긴 하지만, 두가지 형태나 기능이 조금 달라서 두 가지 형태를 구분하여 정리하고자 한다.


첫 번째는 new Factory().create("문자") 를 사용하여 create() 내부 구현에서 if문을 이용하여 인자별로 별도의 인스턴스를 생성하여 리턴 해주는 패턴.

두 번째는 abstract Factory Class를 생성하고 create 기능은 추상화 하고 상속받는 하위 클래스 에서 개별 기능을 구현하는 abstract Factory Pattern.


나도 처음 접해본 케이스는 MVC패턴으로 웹개발을 하는 경우 Command객체나 Action객체 (혹은 Service객체)를 url요청에 따라서 리턴하여 주는 첫번 째 케이스의 Factory사용이였던 것 같다. (참조) 웹에서 사용하는 경우는 Factory 클래스를 Singleton으로 작성하여 Action객체 등을 생성하여 리턴 받는다.


성격에 따라 달리 쓰이는 것 같다. 이해를 돕기 위해서 두 가지 경우 모두 정리하여 보도록 해야겠다. 


용도

  • 클래스의 인스턴스 생성을 별도 클래스에 위임 할 때 사용

 

사용방법

  • 클라이언트 측에서 Factory 클래스 인스턴스를 만들고 crate() 등의 메서드에서 new키워드로 인스턴스를 생성하여 리턴한다.

 




Example#1 Factory Method Pattern

 굉장히 심플하게 작성된 예제로 Factory Class에서 create 메소드로 넘어온 인자에 따라 IProduct 구현체를 결정하여 생성하고 리턴하여 준다.

[IProduct Interface]

Factory에서 생성 될 Class의 Interface를 지정 한다.

1
2
3
4
5
6
package com.product;
 
// 상품 인터페이스
public interface IProduct {
    public void print();
}
cs


[AProduct Interface]

IProduct를 구현한 AProduct구현체

1
2
3
4
5
6
7
8
package com.product;
 
public class AProduct implements IProduct{
    @Override
    public void print() {
        System.out.println("I am A Product");
    }
}
cs

(BProduct, CProduct 동일)


[Factory Class]

create method 인자 type에 따라 분기하여 객체를 생성하여 리턴한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.factory;
 
import com.product.*;
 
public class Factory {
    
    public IProduct create(String type) {
 
        IProduct p = null;
        
        switch (type) {
        case "A":
            p = new AProduct();
            break;
        case "B":
            p = new BProduct();
            break;
        case "C":
            p = new CProduct();
            break;
        default:
            break;
        }
        
        return p;
    }
}
cs


[MainApplication Class]

클라이언트 측에서 아래와 같은 형태로 객체를 생성한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.main;
import com.factory.Factory;
import com.product.IProduct;
 
public class MainApplication {
 
    public static void main(String[] args) {
        
        Factory factory = new Factory();
        
        IProduct a = factory.create("A");
        IProduct b = factory.create("B");
        IProduct c = factory.create("C");
 
        a.print();
        b.print();
        c.print();
 
    }
 
}
cs



수행결과

I am A Product

I am B Product

I am C Product



다운로드


FactoryMethodPattern.zip






Example#2 Abstract Factory Method Pattern 

abstract Factory Method Pattern은 사실 뜯어보면 Template Method 패턴과 Factory Pattern을 합쳐 놓은 형태다. Template Method 패턴으로 상위 추상클래스에서 핵심 기능을 final method로 지정하고 하위 Factory 클래스에서는 추가 기능을 구현하면서 객체를 생성해주는 패턴이다. 설명해봐야 복잡하기만 하다. 예제를 보는게 가장 간편하다.

 



[Factory Class]

핵심기능은 create() 메소드이고 final로 지정해두었다. 이는 Template Method 패턴에 가까운 방법

나머지 abstract method는 부가 기능이지 핵심 기능은 아니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.framework;
 
// 추상클래스 정의
public abstract class Factory {
    
    // final 키워드로 정의된 메소드는 하위클래스에서 override 불가
    public final Product create(String owner) {
        Product p = createProduct(owner);
        registerProduct(p);
        return p;
    }
    
    // abstract는 하위 클래스가 abstract가 아닌 경우 반드시 override 해야 한다.
    protected abstract Product createProduct(String owner);
    protected abstract void registerProduct(Product product);
 
}
cs

 


[IDCardFactory Class]

Factory Class를 상속받아 abstract method를 전부 구현한 구현체

본 Class에 create는 보이지 않지만 상위 클래스인 Factory에 존재 한다.

상위 클래스 create() -> 하위클래스 createProduct() -> 하위클래스 registerProduct() 의 순서로 동작한다.

만약 abstract로 상위클래스에서 create()를 정의하지는 않는다면 이를 전부 IDCard 생성시 마다 하나씩 호출한다면 소스코드가 복잡해지고 지저분해진다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.idcard;
 
import java.util.ArrayList;
import java.util.List;
 
import com.framework.Factory;
import com.framework.Product;
 
public class IDCardFactory extends Factory {
    
    private List<String> owners = new ArrayList<String>();
    
    @Override
    protected Product createProduct(String owner) {
        return new IDCard(owner);
    }
 
    @Override
    protected void registerProduct(Product product) {
        owners.add(((IDCard)product).getOwner());
    }
 
    public List<String> getOwners() {
        return owners;
    }
}
cs


[Product Class]

1
2
3
4
5
6
package com.framework;
 
// 추상클래스 정의 
public abstract class Product {
    public abstract void use();
}
cs


[IDCard Class]

Product의 구현체로 Product를 상속받는 다는 것 말고 중요한 건 없다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.idcard;
 
import com.framework.Product;
 
public class IDCard extends Product {
    private String owner;
    
    public IDCard(String owner) {
        System.out.println(owner + "의 카드 생성");
        this.owner = owner;
    }
 
    // abstract 클래스 Product의 abstract 메소드 override
    @Override
    public void use() {
        System.out.println(owner + "의 카드 사용");
    }
 
    public String getOwner() {
        return owner;
    }
}
cs


[MainApplication Class]

사용자체는 일반 Factory Pattern과 동일하다.

Template Method Pattern을 통해서 반복작업을 final 메소드로 자동 처리 하는 점이 포인트다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import com.framework.Product;
import com.idcard.IDCardFactory;
 
public class MainApplication {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        IDCardFactory factory = new IDCardFactory();
        
        Product card1 = factory.create("루피");
        Product card2 = factory.create("나미");
        Product card3 = factory.create("조로");
        
        System.out.println("LENGTH : " + factory.getOwners().size());
 
        card1.use();
        card2.use();
        card3.use();
        
        
    }
 
}
cs


수행결과

루피의 카드 생성

나미의 카드 생성

조로의 카드 생성

LENGTH : 3

루피의 카드 사용

나미의 카드 사용

조로의 카드 사용



다운로드


abstractFactoryMethodPattern.zip




'프로그래밍 > Design Pattern' 카테고리의 다른 글

Singleton Pattern  (0) 2015.12.29

이 글을 공유하기

댓글

Email by JB FACTORY