본문 바로가기

DesignPattern

Factory pattern

Factory 패턴

팩토리 메소드 패턴은 인스턴스를 만드는 방법을 상위클래스 측에서 결정.

하위클래스에서 구체적인 처리의 내용 하위 클래스에서 구현.

예제는 다섯개의 클래스로 구성

frame pakage;

– Product class  : 추상 메소드 use 만 정의된 추상클래스

– Factory class : 메소드 create 을 구현하는 추상 클래스

idcard pakage

– IDCard class : 메소드 use를 구현

– IDCardFactory class : 메소드 createProduct, registerProduct 를 구현하고 있는 클래스

Anonymous pakage

– Main class : 동작 테스트 클래스

FactoryUML

Product .java

package framework;

public abstract class Product {
public abstract void use();
}

 

Factory.java

package framework;

public abstract class Factory {

public final Product create(String owner){
Product p = createProduct(owner);

registerProduct(p);

return p;
}

protected abstract void registerProduct(Product product);

protected abstract Product createProduct(String owner);
}

framework 패키지의 Factory 클래스는 createProduct 추상 메소드를 만들도록 규정, registerProduct는 Product객체를 등록하는 메소드

이 때 중요한 것이 Factory 추상 메소드에서 구현 흐름!!

Product p 자료형의 createProduct(owner)메소드를 정의하고

registerProduct(p);을 실행한 뒤 p를 리턴한다.

 

IDCard.java

 

package idcard;

import framework.Product;

public class IDCard extends Product{

private String owner;
IDCard(String owner){

System.out.println(owner+”카드를 만듭니다.”);
this.owner=owner;
}

public void use() {
// TODO Auto-generated method stub
System.out.println(owner+”카드를 사용합니다.”);
}
public String getOwner(){
return owner;
}

}

Product를 상속받아 use()메소드를 구현한다. 여기서는 IDCard 생성자를 통해 owner를 받고, 출력한뒤 멤버 변수에 넣는다.

 

IDCardFactory.java

 

package idcard;

import java.util.ArrayList;
import java.util.List;

import framework.Factory;
import framework.Product;

public class IDCardFactory extends Factory{

private List owners = new ArrayList();

protected void registerProduct(Product product) {
// TODO Auto-generated method stub
owners.add(((IDCard)product).getOwner());
}
protected Product createProduct(String owner) {
// TODO Auto-generated method stub

return new IDCard(owner);
}

}

여기서는 register메소드 구현을 위해 owners 라는 배열을 선언했다.(ArrayList) Factory를 상속 받았기에 createProduct와 registerProduct()메소드를 구현 하면 Factory 클래스에 구현 흐름에 따라 처리된다.

Main.java

 

package Anonymous;

import framework.Factory;
import framework.Product;
import idcard.IDCardFactory;

public class Main {

public static void main(String[] args) {
// TODO Auto-generated method stub

Factory factory = new IDCardFactory();
Product card1 = factory.create(“홍길동”);

card1.use();

}

}

출력

 

홍길동카드를 만듭니다.
홍길동카드를 사용합니다.

 

Factory 클래스의 createProduct 메소드는 추상 메소드이며, 하위클래스 에서 구현한다.

다른 방법으로는

1. 디폴트의 구현을 준비해둔다.

classFactory{

pulbic Product createProduct(String name) {

return new Product(name)

}

}

이 경우에는 Product 클래스에 직접 new를 이용하고 있어서 Product클래스를 추상클래스로 둘 수 없다.

2.  에러를 이용한다.

classFactory{

pulbic Product createProduct(String name) {

throw new RuntimeException();

}

}

디폴트의 구현 내용을 에러로 처리해두면, 하위클래스에서 구현하지 않을 경우 실행할때, 에러가 발생.

 

연습문제.

IDCard의 생성자가 public 이 아닌 이유는 ?

디폴트 생성자는 동일한 패키지 내에서만 사용가능

IDCard 인스턴스를 패키지 외부로 부터 new 를 사용하여 생성할 수없게끔 반드시 IDCardFactory를 경유해야 하기 때문에

public abstract class Product {

public abstract Product (String name );

public abstract void use();

}

에서 에러가 나는 이유는?

abstract한 생성자 생성 불가능 java에서 생성자는 상속되지 않기 때문에 abstract한 생성자는 의미 없음

결론.. 음 .. 좀 헷갈리지만 전체적으로 템플릿 메소드의 확장? 정도로 생각하련다. 중요한 점은 하위클래스에 위임을 하는 점과 , 전체적인 구현흐름을 추상클래스에서 정의해놓고, 구현하면 각각의 유지보수, 코드의 재이용성, 수정, 특히나 확장 면에서 유리하게 써먹을 수있다는점


'DesignPattern' 카테고리의 다른 글

Clean Architecture 번역  (0) 2017.12.26
Singlton pattern  (0) 2016.05.18
template pattern  (0) 2016.05.18
Iterator Pattern  (0) 2016.05.18
Adapter Pattern  (0) 2016.05.18